summaryrefslogtreecommitdiffstats
path: root/Source/ThirdParty
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-06 11:45:16 +0100
committerSteve Block <steveblock@google.com>2011-05-12 13:44:10 +0100
commitcad810f21b803229eb11403f9209855525a25d57 (patch)
tree29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/ThirdParty
parent121b0cf4517156d0ac5111caf9830c51b69bae8f (diff)
downloadexternal_webkit-cad810f21b803229eb11403f9209855525a25d57.zip
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/ThirdParty')
-rw-r--r--Source/ThirdParty/ANGLE/ANGLE.xcodeproj/project.pbxproj621
-rw-r--r--Source/ThirdParty/ANGLE/ChangeLog582
-rw-r--r--Source/ThirdParty/ANGLE/Configurations/ANGLE.xcconfig5
-rw-r--r--Source/ThirdParty/ANGLE/Configurations/Base.xcconfig54
-rw-r--r--Source/ThirdParty/ANGLE/Configurations/DebugRelease.xcconfig19
-rw-r--r--Source/ThirdParty/ANGLE/Makefile1
-rw-r--r--Source/ThirdParty/ANGLE/include/EGL/egl.h329
-rw-r--r--Source/ThirdParty/ANGLE/include/EGL/eglext.h222
-rw-r--r--Source/ThirdParty/ANGLE/include/EGL/eglplatform.h110
-rw-r--r--Source/ThirdParty/ANGLE/include/GLES2/gl2.h621
-rw-r--r--Source/ThirdParty/ANGLE/include/GLES2/gl2ext.h831
-rw-r--r--Source/ThirdParty/ANGLE/include/GLES2/gl2platform.h30
-rw-r--r--Source/ThirdParty/ANGLE/include/GLSLANG/ShaderLang.h128
-rw-r--r--Source/ThirdParty/ANGLE/include/KHR/khrplatform.h269
-rw-r--r--Source/ThirdParty/ANGLE/src/build_angle.xcodeproj/project.pbxproj620
-rw-r--r--Source/ThirdParty/ANGLE/src/common/angleutils.h18
-rw-r--r--Source/ThirdParty/ANGLE/src/common/debug.cpp38
-rw-r--r--Source/ThirdParty/ANGLE/src/common/debug.h65
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/BaseTypes.h147
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/CodeGenGLSL.cpp25
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/CodeGenHLSL.cpp25
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/Common.h76
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/ConstantUnion.h288
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/InfoSink.cpp59
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/InfoSink.h114
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/Initialize.cpp617
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/Initialize.h33
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/InitializeDll.cpp115
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/InitializeDll.h16
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/InitializeGlobals.h15
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/InitializeParseContext.h16
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/IntermTraverse.cpp293
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/Intermediate.cpp1386
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/MMap.h56
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.cpp677
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.h49
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp2160
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.h127
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/ParseHelper.cpp1479
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/ParseHelper.h123
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.cpp318
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.h304
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/QualifierAlive.cpp58
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/QualifierAlive.h7
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/RemoveTree.cpp77
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/RemoveTree.h7
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/ShHandle.h76
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/ShaderLang.cpp311
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/SymbolTable.cpp216
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/SymbolTable.h331
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.cpp20
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.h18
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.cpp24
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.h18
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/Types.h293
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.cpp63
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.h35
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/debug.cpp36
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/debug.h53
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/glslang.l600
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/glslang.y2178
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/intermOut.cpp417
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/intermediate.h517
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/localintermediate.h58
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/osinclude.h62
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/ossource_posix.cpp64
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/ossource_win.cpp57
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/parseConst.cpp238
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/preprocessor/atom.c735
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/preprocessor/atom.h63
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/preprocessor/compile.h99
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.c1024
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.h86
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/preprocessor/cppstruct.c152
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/preprocessor/memory.c154
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/preprocessor/memory.h56
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/preprocessor/parser.h93
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/preprocessor/preprocess.h51
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/preprocessor/scanner.c759
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/preprocessor/scanner.h85
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/preprocessor/slglobals.h82
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/preprocessor/symbols.c284
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/preprocessor/symbols.h112
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/preprocessor/tokens.c439
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/preprocessor/tokens.h89
-rw-r--r--Source/ThirdParty/ANGLE/src/compiler/unistd.h1
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/Config.cpp397
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/Config.h118
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/Display.cpp490
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/Display.h98
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp431
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/Surface.h83
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/libEGL.cpp1084
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/libEGL.def36
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/libEGL.vcproj252
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/main.cpp161
-rw-r--r--Source/ThirdParty/ANGLE/src/libEGL/main.h60
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Blit.cpp566
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Blit.h90
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.cpp56
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.h50
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp3319
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Context.h480
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.cpp455
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.h96
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Program.cpp2806
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Program.h232
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/RefCountObject.cpp51
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/RefCountObject.h70
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.cpp484
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.h175
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.cpp340
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.h92
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Shader.cpp504
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Shader.h157
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp1817
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Texture.h283
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp261
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.h71
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.cpp271
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.h66
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/geometry/backend.cpp38
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/geometry/backend.h110
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/geometry/dx9.cpp613
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/geometry/dx9.h137
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/geometry/vertexconversion.h208
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.cpp5451
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.def156
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.vcproj365
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/main.cpp143
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/main.h47
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/mathutil.h66
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/utilities.cpp674
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/utilities.h68
-rw-r--r--Source/ThirdParty/Makefile17
-rw-r--r--Source/ThirdParty/Makefile.shared2
136 files changed, 47376 insertions, 0 deletions
diff --git a/Source/ThirdParty/ANGLE/ANGLE.xcodeproj/project.pbxproj b/Source/ThirdParty/ANGLE/ANGLE.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..066a930
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/ANGLE.xcodeproj/project.pbxproj
@@ -0,0 +1,621 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 42;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ FB39D2711200F35A00088E69 /* CodeGenGLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D2221200F35A00088E69 /* CodeGenGLSL.cpp */; };
+ FB39D2751200F35A00088E69 /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D2261200F35A00088E69 /* debug.cpp */; };
+ FB39D2791200F35A00088E69 /* InfoSink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D22A1200F35A00088E69 /* InfoSink.cpp */; };
+ FB39D27B1200F35A00088E69 /* Initialize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D22C1200F35A00088E69 /* Initialize.cpp */; };
+ FB39D27D1200F35A00088E69 /* InitializeDll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D22E1200F35A00088E69 /* InitializeDll.cpp */; };
+ FB39D2811200F35A00088E69 /* Intermediate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D2321200F35A00088E69 /* Intermediate.cpp */; };
+ FB39D2831200F35A00088E69 /* intermOut.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D2341200F35A00088E69 /* intermOut.cpp */; };
+ FB39D2841200F35A00088E69 /* IntermTraverse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D2351200F35A00088E69 /* IntermTraverse.cpp */; };
+ FB39D2881200F35A00088E69 /* ossource_posix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D2391200F35A00088E69 /* ossource_posix.cpp */; };
+ FB39D28A1200F35A00088E69 /* OutputGLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D23B1200F35A00088E69 /* OutputGLSL.cpp */; };
+ FB39D28E1200F35A00088E69 /* parseConst.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D23F1200F35A00088E69 /* parseConst.cpp */; };
+ FB39D28F1200F35A00088E69 /* ParseHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D2401200F35A00088E69 /* ParseHelper.cpp */; };
+ FB39D2911200F35A00088E69 /* PoolAlloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D2421200F35A00088E69 /* PoolAlloc.cpp */; };
+ FB39D2931200F35A00088E69 /* atom.c in Sources */ = {isa = PBXBuildFile; fileRef = FB39D2451200F35A00088E69 /* atom.c */; };
+ FB39D2961200F35A00088E69 /* cpp.c in Sources */ = {isa = PBXBuildFile; fileRef = FB39D2481200F35A00088E69 /* cpp.c */; };
+ FB39D2981200F35A00088E69 /* cppstruct.c in Sources */ = {isa = PBXBuildFile; fileRef = FB39D24A1200F35A00088E69 /* cppstruct.c */; };
+ FB39D2991200F35A00088E69 /* memory.c in Sources */ = {isa = PBXBuildFile; fileRef = FB39D24B1200F35A00088E69 /* memory.c */; };
+ FB39D29D1200F35A00088E69 /* scanner.c in Sources */ = {isa = PBXBuildFile; fileRef = FB39D24F1200F35A00088E69 /* scanner.c */; };
+ FB39D2A01200F35A00088E69 /* symbols.c in Sources */ = {isa = PBXBuildFile; fileRef = FB39D2521200F35A00088E69 /* symbols.c */; };
+ FB39D2A21200F35A00088E69 /* tokens.c in Sources */ = {isa = PBXBuildFile; fileRef = FB39D2541200F35A00088E69 /* tokens.c */; };
+ FB39D2A41200F35A00088E69 /* QualifierAlive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D2561200F35A00088E69 /* QualifierAlive.cpp */; };
+ FB39D2A61200F35A00088E69 /* RemoveTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D2581200F35A00088E69 /* RemoveTree.cpp */; };
+ FB39D2A81200F35A00088E69 /* ShaderLang.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D25A1200F35A00088E69 /* ShaderLang.cpp */; };
+ FB39D2AA1200F35A00088E69 /* SymbolTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D25C1200F35A00088E69 /* SymbolTable.cpp */; };
+ FB39D2AC1200F35A00088E69 /* TranslatorGLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D2681200F35A00088E69 /* TranslatorGLSL.cpp */; };
+ FB39D2B11200F35A00088E69 /* UnfoldSelect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D26D1200F35A00088E69 /* UnfoldSelect.cpp */; };
+ FB39D7231201032000088E69 /* glslang.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D7201201032000088E69 /* glslang.cpp */; };
+ FB39D7241201032000088E69 /* glslang_tab.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D7221201032000088E69 /* glslang_tab.cpp */; };
+ FB39D76E120110FC00088E69 /* ShaderLang.h in Headers */ = {isa = PBXBuildFile; fileRef = FB39D2BF1200F3E600088E69 /* ShaderLang.h */; settings = {ATTRIBUTES = (Public, ); }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 5D7C59C51208C68B001C873E /* ANGLE.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ANGLE.xcconfig; sourceTree = "<group>"; };
+ 5D7C59C61208C68B001C873E /* Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = "<group>"; };
+ 5D7C59C71208C68B001C873E /* DebugRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugRelease.xcconfig; sourceTree = "<group>"; };
+ FB39D0D11200F0E300088E69 /* libANGLE.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libANGLE.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ FB39D1861200F26200088E69 /* BaseTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseTypes.h; sourceTree = "<group>"; };
+ FB39D1871200F26200088E69 /* CodeGenGLSL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = CodeGenGLSL.cpp; sourceTree = "<group>"; };
+ FB39D1881200F26200088E69 /* CodeGenHLSL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = CodeGenHLSL.cpp; sourceTree = "<group>"; };
+ FB39D1891200F26200088E69 /* Common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Common.h; sourceTree = "<group>"; };
+ FB39D18A1200F26200088E69 /* ConstantUnion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantUnion.h; sourceTree = "<group>"; };
+ FB39D18B1200F26200088E69 /* debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = debug.cpp; sourceTree = "<group>"; };
+ FB39D18C1200F26200088E69 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = "<group>"; };
+ FB39D18D1200F26200088E69 /* glslang.l */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.lex; path = glslang.l; sourceTree = "<group>"; };
+ FB39D18E1200F26200088E69 /* glslang.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; path = glslang.y; sourceTree = "<group>"; };
+ FB39D18F1200F26200088E69 /* InfoSink.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = InfoSink.cpp; sourceTree = "<group>"; };
+ FB39D1901200F26200088E69 /* InfoSink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InfoSink.h; sourceTree = "<group>"; };
+ FB39D1911200F26200088E69 /* Initialize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = Initialize.cpp; sourceTree = "<group>"; };
+ FB39D1921200F26200088E69 /* Initialize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Initialize.h; sourceTree = "<group>"; };
+ FB39D1931200F26200088E69 /* InitializeDll.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = InitializeDll.cpp; sourceTree = "<group>"; };
+ FB39D1941200F26200088E69 /* InitializeDll.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InitializeDll.h; sourceTree = "<group>"; };
+ FB39D1951200F26200088E69 /* InitializeGlobals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InitializeGlobals.h; sourceTree = "<group>"; };
+ FB39D1961200F26200088E69 /* InitializeParseContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InitializeParseContext.h; sourceTree = "<group>"; };
+ FB39D1971200F26200088E69 /* Intermediate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = Intermediate.cpp; sourceTree = "<group>"; };
+ FB39D1981200F26200088E69 /* intermediate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = intermediate.h; sourceTree = "<group>"; };
+ FB39D1991200F26200088E69 /* intermOut.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = intermOut.cpp; sourceTree = "<group>"; };
+ FB39D19A1200F26200088E69 /* IntermTraverse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = IntermTraverse.cpp; sourceTree = "<group>"; };
+ FB39D19B1200F26200088E69 /* localintermediate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = localintermediate.h; sourceTree = "<group>"; };
+ FB39D19C1200F26200088E69 /* MMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMap.h; sourceTree = "<group>"; };
+ FB39D19D1200F26200088E69 /* osinclude.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = osinclude.h; sourceTree = "<group>"; };
+ FB39D19E1200F26200088E69 /* ossource_posix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = ossource_posix.cpp; sourceTree = "<group>"; };
+ FB39D19F1200F26200088E69 /* ossource_win.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = ossource_win.cpp; sourceTree = "<group>"; };
+ FB39D1A01200F26200088E69 /* OutputGLSL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = OutputGLSL.cpp; sourceTree = "<group>"; };
+ FB39D1A11200F26200088E69 /* OutputGLSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OutputGLSL.h; sourceTree = "<group>"; };
+ FB39D1A21200F26200088E69 /* OutputHLSL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = OutputHLSL.cpp; sourceTree = "<group>"; };
+ FB39D1A31200F26200088E69 /* OutputHLSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OutputHLSL.h; sourceTree = "<group>"; };
+ FB39D1A41200F26200088E69 /* parseConst.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = parseConst.cpp; sourceTree = "<group>"; };
+ FB39D1A51200F26200088E69 /* ParseHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = ParseHelper.cpp; sourceTree = "<group>"; };
+ FB39D1A61200F26200088E69 /* ParseHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseHelper.h; sourceTree = "<group>"; };
+ FB39D1A71200F26200088E69 /* PoolAlloc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = PoolAlloc.cpp; sourceTree = "<group>"; };
+ FB39D1A81200F26200088E69 /* PoolAlloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PoolAlloc.h; sourceTree = "<group>"; };
+ FB39D1AA1200F26200088E69 /* atom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = atom.c; sourceTree = "<group>"; };
+ FB39D1AB1200F26200088E69 /* atom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = atom.h; sourceTree = "<group>"; };
+ FB39D1AC1200F26200088E69 /* compile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = compile.h; sourceTree = "<group>"; };
+ FB39D1AD1200F26200088E69 /* cpp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cpp.c; sourceTree = "<group>"; };
+ FB39D1AE1200F26200088E69 /* cpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpp.h; sourceTree = "<group>"; };
+ FB39D1AF1200F26200088E69 /* cppstruct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cppstruct.c; sourceTree = "<group>"; };
+ FB39D1B01200F26200088E69 /* memory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = memory.c; sourceTree = "<group>"; };
+ FB39D1B11200F26200088E69 /* memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory.h; sourceTree = "<group>"; };
+ FB39D1B21200F26200088E69 /* parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parser.h; sourceTree = "<group>"; };
+ FB39D1B31200F26200088E69 /* preprocess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = preprocess.h; sourceTree = "<group>"; };
+ FB39D1B41200F26200088E69 /* scanner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scanner.c; sourceTree = "<group>"; };
+ FB39D1B51200F26200088E69 /* scanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scanner.h; sourceTree = "<group>"; };
+ FB39D1B61200F26200088E69 /* slglobals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = slglobals.h; sourceTree = "<group>"; };
+ FB39D1B71200F26200088E69 /* symbols.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = symbols.c; sourceTree = "<group>"; };
+ FB39D1B81200F26200088E69 /* symbols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = symbols.h; sourceTree = "<group>"; };
+ FB39D1B91200F26200088E69 /* tokens.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tokens.c; sourceTree = "<group>"; };
+ FB39D1BA1200F26200088E69 /* tokens.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tokens.h; sourceTree = "<group>"; };
+ FB39D1BB1200F26200088E69 /* QualifierAlive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = QualifierAlive.cpp; sourceTree = "<group>"; };
+ FB39D1BC1200F26200088E69 /* QualifierAlive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QualifierAlive.h; sourceTree = "<group>"; };
+ FB39D1BD1200F26200088E69 /* RemoveTree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = RemoveTree.cpp; sourceTree = "<group>"; };
+ FB39D1BE1200F26200088E69 /* RemoveTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoveTree.h; sourceTree = "<group>"; };
+ FB39D1BF1200F26200088E69 /* ShaderLang.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; includeInIndex = 0; path = ShaderLang.cpp; sourceTree = "<group>"; };
+ FB39D1C01200F26200088E69 /* ShHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShHandle.h; sourceTree = "<group>"; };
+ FB39D1C11200F26200088E69 /* SymbolTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolTable.cpp; sourceTree = "<group>"; };
+ FB39D1C21200F26200088E69 /* SymbolTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolTable.h; sourceTree = "<group>"; };
+ FB39D1CB1200F26200088E69 /* translator_common.vcproj */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = translator_common.vcproj; sourceTree = "<group>"; };
+ FB39D1CC1200F26200088E69 /* translator_hlsl.vcproj */ = {isa = PBXFileReference; explicitFileType = text.xml; fileEncoding = 4; path = translator_hlsl.vcproj; sourceTree = "<group>"; };
+ FB39D1CD1200F26200088E69 /* TranslatorGLSL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = TranslatorGLSL.cpp; sourceTree = "<group>"; };
+ FB39D1CE1200F26200088E69 /* TranslatorGLSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TranslatorGLSL.h; sourceTree = "<group>"; };
+ FB39D1CF1200F26200088E69 /* TranslatorHLSL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = TranslatorHLSL.cpp; sourceTree = "<group>"; };
+ FB39D1D01200F26200088E69 /* TranslatorHLSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TranslatorHLSL.h; sourceTree = "<group>"; };
+ FB39D1D11200F26200088E69 /* Types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Types.h; sourceTree = "<group>"; };
+ FB39D1D21200F26200088E69 /* UnfoldSelect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = UnfoldSelect.cpp; sourceTree = "<group>"; };
+ FB39D1D31200F26200088E69 /* UnfoldSelect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnfoldSelect.h; sourceTree = "<group>"; };
+ FB39D1D41200F26200088E69 /* unistd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unistd.h; sourceTree = "<group>"; };
+ FB39D2211200F35A00088E69 /* BaseTypes.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = BaseTypes.h; sourceTree = "<group>"; };
+ FB39D2221200F35A00088E69 /* CodeGenGLSL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeGenGLSL.cpp; sourceTree = "<group>"; };
+ FB39D2241200F35A00088E69 /* Common.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = Common.h; sourceTree = "<group>"; };
+ FB39D2251200F35A00088E69 /* ConstantUnion.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = ConstantUnion.h; sourceTree = "<group>"; };
+ FB39D2261200F35A00088E69 /* debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug.cpp; sourceTree = "<group>"; };
+ FB39D2271200F35A00088E69 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = "<group>"; };
+ FB39D2281200F35A00088E69 /* glslang.l */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.lex; path = glslang.l; sourceTree = "<group>"; };
+ FB39D2291200F35A00088E69 /* glslang.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; path = glslang.y; sourceTree = "<group>"; };
+ FB39D22A1200F35A00088E69 /* InfoSink.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InfoSink.cpp; sourceTree = "<group>"; };
+ FB39D22B1200F35A00088E69 /* InfoSink.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = InfoSink.h; sourceTree = "<group>"; };
+ FB39D22C1200F35A00088E69 /* Initialize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Initialize.cpp; sourceTree = "<group>"; };
+ FB39D22D1200F35A00088E69 /* Initialize.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = Initialize.h; sourceTree = "<group>"; };
+ FB39D22E1200F35A00088E69 /* InitializeDll.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InitializeDll.cpp; sourceTree = "<group>"; };
+ FB39D22F1200F35A00088E69 /* InitializeDll.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = InitializeDll.h; sourceTree = "<group>"; };
+ FB39D2301200F35A00088E69 /* InitializeGlobals.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = InitializeGlobals.h; sourceTree = "<group>"; };
+ FB39D2311200F35A00088E69 /* InitializeParseContext.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = InitializeParseContext.h; sourceTree = "<group>"; };
+ FB39D2321200F35A00088E69 /* Intermediate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Intermediate.cpp; sourceTree = "<group>"; };
+ FB39D2331200F35A00088E69 /* intermediate.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = intermediate.h; sourceTree = "<group>"; };
+ FB39D2341200F35A00088E69 /* intermOut.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = intermOut.cpp; sourceTree = "<group>"; };
+ FB39D2351200F35A00088E69 /* IntermTraverse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntermTraverse.cpp; sourceTree = "<group>"; };
+ FB39D2361200F35A00088E69 /* localintermediate.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = localintermediate.h; sourceTree = "<group>"; };
+ FB39D2371200F35A00088E69 /* MMap.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = MMap.h; sourceTree = "<group>"; };
+ FB39D2381200F35A00088E69 /* osinclude.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = osinclude.h; sourceTree = "<group>"; };
+ FB39D2391200F35A00088E69 /* ossource_posix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossource_posix.cpp; sourceTree = "<group>"; };
+ FB39D23A1200F35A00088E69 /* ossource_win.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossource_win.cpp; sourceTree = "<group>"; };
+ FB39D23B1200F35A00088E69 /* OutputGLSL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OutputGLSL.cpp; sourceTree = "<group>"; };
+ FB39D23C1200F35A00088E69 /* OutputGLSL.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = OutputGLSL.h; sourceTree = "<group>"; };
+ FB39D23F1200F35A00088E69 /* parseConst.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parseConst.cpp; sourceTree = "<group>"; };
+ FB39D2401200F35A00088E69 /* ParseHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParseHelper.cpp; sourceTree = "<group>"; };
+ FB39D2411200F35A00088E69 /* ParseHelper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = ParseHelper.h; sourceTree = "<group>"; };
+ FB39D2421200F35A00088E69 /* PoolAlloc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PoolAlloc.cpp; sourceTree = "<group>"; };
+ FB39D2431200F35A00088E69 /* PoolAlloc.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = PoolAlloc.h; sourceTree = "<group>"; };
+ FB39D2451200F35A00088E69 /* atom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = atom.c; sourceTree = "<group>"; };
+ FB39D2461200F35A00088E69 /* atom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = atom.h; sourceTree = "<group>"; };
+ FB39D2471200F35A00088E69 /* compile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = compile.h; sourceTree = "<group>"; };
+ FB39D2481200F35A00088E69 /* cpp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cpp.c; sourceTree = "<group>"; };
+ FB39D2491200F35A00088E69 /* cpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpp.h; sourceTree = "<group>"; };
+ FB39D24A1200F35A00088E69 /* cppstruct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cppstruct.c; sourceTree = "<group>"; };
+ FB39D24B1200F35A00088E69 /* memory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = memory.c; sourceTree = "<group>"; };
+ FB39D24C1200F35A00088E69 /* memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory.h; sourceTree = "<group>"; };
+ FB39D24D1200F35A00088E69 /* parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parser.h; sourceTree = "<group>"; };
+ FB39D24E1200F35A00088E69 /* preprocess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = preprocess.h; sourceTree = "<group>"; };
+ FB39D24F1200F35A00088E69 /* scanner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scanner.c; sourceTree = "<group>"; };
+ FB39D2501200F35A00088E69 /* scanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scanner.h; sourceTree = "<group>"; };
+ FB39D2511200F35A00088E69 /* slglobals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = slglobals.h; sourceTree = "<group>"; };
+ FB39D2521200F35A00088E69 /* symbols.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = symbols.c; sourceTree = "<group>"; };
+ FB39D2531200F35A00088E69 /* symbols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = symbols.h; sourceTree = "<group>"; };
+ FB39D2541200F35A00088E69 /* tokens.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tokens.c; sourceTree = "<group>"; };
+ FB39D2551200F35A00088E69 /* tokens.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tokens.h; sourceTree = "<group>"; };
+ FB39D2561200F35A00088E69 /* QualifierAlive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = QualifierAlive.cpp; sourceTree = "<group>"; };
+ FB39D2571200F35A00088E69 /* QualifierAlive.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = QualifierAlive.h; sourceTree = "<group>"; };
+ FB39D2581200F35A00088E69 /* RemoveTree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RemoveTree.cpp; sourceTree = "<group>"; };
+ FB39D2591200F35A00088E69 /* RemoveTree.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = RemoveTree.h; sourceTree = "<group>"; };
+ FB39D25A1200F35A00088E69 /* ShaderLang.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShaderLang.cpp; sourceTree = "<group>"; };
+ FB39D25B1200F35A00088E69 /* ShHandle.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = ShHandle.h; sourceTree = "<group>"; };
+ FB39D25C1200F35A00088E69 /* SymbolTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolTable.cpp; sourceTree = "<group>"; };
+ FB39D25D1200F35A00088E69 /* SymbolTable.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = SymbolTable.h; sourceTree = "<group>"; };
+ FB39D2681200F35A00088E69 /* TranslatorGLSL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TranslatorGLSL.cpp; sourceTree = "<group>"; };
+ FB39D2691200F35A00088E69 /* TranslatorGLSL.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = TranslatorGLSL.h; sourceTree = "<group>"; };
+ FB39D26C1200F35A00088E69 /* Types.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = Types.h; sourceTree = "<group>"; };
+ FB39D26D1200F35A00088E69 /* UnfoldSelect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnfoldSelect.cpp; sourceTree = "<group>"; };
+ FB39D26E1200F35A00088E69 /* UnfoldSelect.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = UnfoldSelect.h; sourceTree = "<group>"; };
+ FB39D26F1200F35A00088E69 /* unistd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unistd.h; sourceTree = "<group>"; };
+ FB39D2BF1200F3E600088E69 /* ShaderLang.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = ShaderLang.h; sourceTree = "<group>"; };
+ FB39D7201201032000088E69 /* glslang.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = glslang.cpp; path = DerivedSources/ANGLE/glslang.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
+ FB39D7211201032000088E69 /* glslang_tab.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = glslang_tab.h; path = DerivedSources/ANGLE/glslang_tab.h; sourceTree = BUILT_PRODUCTS_DIR; };
+ FB39D7221201032000088E69 /* glslang_tab.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = glslang_tab.cpp; path = DerivedSources/ANGLE/glslang_tab.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ FB39D0CF1200F0E300088E69 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 5D7C59C41208C68B001C873E /* Configurations */ = {
+ isa = PBXGroup;
+ children = (
+ 5D7C59C51208C68B001C873E /* ANGLE.xcconfig */,
+ 5D7C59C61208C68B001C873E /* Base.xcconfig */,
+ 5D7C59C71208C68B001C873E /* DebugRelease.xcconfig */,
+ );
+ path = Configurations;
+ sourceTree = "<group>";
+ };
+ FB39D06E1200ED9200088E69 = {
+ isa = PBXGroup;
+ children = (
+ FB39D2201200F35A00088E69 /* compiler */,
+ FB39D0841200EDEB00088E69 /* Source */,
+ FB39D0CB1200EF9400088E69 /* Intermediates */,
+ 5D7C59C41208C68B001C873E /* Configurations */,
+ FB39D0CC1200EF9B00088E69 /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ FB39D0841200EDEB00088E69 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ FB39D2BD1200F3E600088E69 /* GLSLANG */,
+ FB39D1851200F26200088E69 /* compiler */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ FB39D0CB1200EF9400088E69 /* Intermediates */ = {
+ isa = PBXGroup;
+ children = (
+ FB39D7201201032000088E69 /* glslang.cpp */,
+ FB39D7211201032000088E69 /* glslang_tab.h */,
+ FB39D7221201032000088E69 /* glslang_tab.cpp */,
+ );
+ name = Intermediates;
+ sourceTree = "<group>";
+ };
+ FB39D0CC1200EF9B00088E69 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ FB39D0D11200F0E300088E69 /* libANGLE.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ FB39D1851200F26200088E69 /* compiler */ = {
+ isa = PBXGroup;
+ children = (
+ FB39D1861200F26200088E69 /* BaseTypes.h */,
+ FB39D1871200F26200088E69 /* CodeGenGLSL.cpp */,
+ FB39D1881200F26200088E69 /* CodeGenHLSL.cpp */,
+ FB39D1891200F26200088E69 /* Common.h */,
+ FB39D18A1200F26200088E69 /* ConstantUnion.h */,
+ FB39D18B1200F26200088E69 /* debug.cpp */,
+ FB39D18C1200F26200088E69 /* debug.h */,
+ FB39D18D1200F26200088E69 /* glslang.l */,
+ FB39D18E1200F26200088E69 /* glslang.y */,
+ FB39D18F1200F26200088E69 /* InfoSink.cpp */,
+ FB39D1901200F26200088E69 /* InfoSink.h */,
+ FB39D1911200F26200088E69 /* Initialize.cpp */,
+ FB39D1921200F26200088E69 /* Initialize.h */,
+ FB39D1931200F26200088E69 /* InitializeDll.cpp */,
+ FB39D1941200F26200088E69 /* InitializeDll.h */,
+ FB39D1951200F26200088E69 /* InitializeGlobals.h */,
+ FB39D1961200F26200088E69 /* InitializeParseContext.h */,
+ FB39D1971200F26200088E69 /* Intermediate.cpp */,
+ FB39D1981200F26200088E69 /* intermediate.h */,
+ FB39D1991200F26200088E69 /* intermOut.cpp */,
+ FB39D19A1200F26200088E69 /* IntermTraverse.cpp */,
+ FB39D19B1200F26200088E69 /* localintermediate.h */,
+ FB39D19C1200F26200088E69 /* MMap.h */,
+ FB39D19D1200F26200088E69 /* osinclude.h */,
+ FB39D19E1200F26200088E69 /* ossource_posix.cpp */,
+ FB39D19F1200F26200088E69 /* ossource_win.cpp */,
+ FB39D1A01200F26200088E69 /* OutputGLSL.cpp */,
+ FB39D1A11200F26200088E69 /* OutputGLSL.h */,
+ FB39D1A21200F26200088E69 /* OutputHLSL.cpp */,
+ FB39D1A31200F26200088E69 /* OutputHLSL.h */,
+ FB39D1A41200F26200088E69 /* parseConst.cpp */,
+ FB39D1A51200F26200088E69 /* ParseHelper.cpp */,
+ FB39D1A61200F26200088E69 /* ParseHelper.h */,
+ FB39D1A71200F26200088E69 /* PoolAlloc.cpp */,
+ FB39D1A81200F26200088E69 /* PoolAlloc.h */,
+ FB39D1A91200F26200088E69 /* preprocessor */,
+ FB39D1BB1200F26200088E69 /* QualifierAlive.cpp */,
+ FB39D1BC1200F26200088E69 /* QualifierAlive.h */,
+ FB39D1BD1200F26200088E69 /* RemoveTree.cpp */,
+ FB39D1BE1200F26200088E69 /* RemoveTree.h */,
+ FB39D1BF1200F26200088E69 /* ShaderLang.cpp */,
+ FB39D1C01200F26200088E69 /* ShHandle.h */,
+ FB39D1C11200F26200088E69 /* SymbolTable.cpp */,
+ FB39D1C21200F26200088E69 /* SymbolTable.h */,
+ FB39D1CB1200F26200088E69 /* translator_common.vcproj */,
+ FB39D1CC1200F26200088E69 /* translator_hlsl.vcproj */,
+ FB39D1CD1200F26200088E69 /* TranslatorGLSL.cpp */,
+ FB39D1CE1200F26200088E69 /* TranslatorGLSL.h */,
+ FB39D1CF1200F26200088E69 /* TranslatorHLSL.cpp */,
+ FB39D1D01200F26200088E69 /* TranslatorHLSL.h */,
+ FB39D1D11200F26200088E69 /* Types.h */,
+ FB39D1D21200F26200088E69 /* UnfoldSelect.cpp */,
+ FB39D1D31200F26200088E69 /* UnfoldSelect.h */,
+ FB39D1D41200F26200088E69 /* unistd.h */,
+ );
+ includeInIndex = 0;
+ name = compiler;
+ path = src/compiler;
+ sourceTree = "<group>";
+ };
+ FB39D1A91200F26200088E69 /* preprocessor */ = {
+ isa = PBXGroup;
+ children = (
+ FB39D1AA1200F26200088E69 /* atom.c */,
+ FB39D1AB1200F26200088E69 /* atom.h */,
+ FB39D1AC1200F26200088E69 /* compile.h */,
+ FB39D1AD1200F26200088E69 /* cpp.c */,
+ FB39D1AE1200F26200088E69 /* cpp.h */,
+ FB39D1AF1200F26200088E69 /* cppstruct.c */,
+ FB39D1B01200F26200088E69 /* memory.c */,
+ FB39D1B11200F26200088E69 /* memory.h */,
+ FB39D1B21200F26200088E69 /* parser.h */,
+ FB39D1B31200F26200088E69 /* preprocess.h */,
+ FB39D1B41200F26200088E69 /* scanner.c */,
+ FB39D1B51200F26200088E69 /* scanner.h */,
+ FB39D1B61200F26200088E69 /* slglobals.h */,
+ FB39D1B71200F26200088E69 /* symbols.c */,
+ FB39D1B81200F26200088E69 /* symbols.h */,
+ FB39D1B91200F26200088E69 /* tokens.c */,
+ FB39D1BA1200F26200088E69 /* tokens.h */,
+ );
+ includeInIndex = 0;
+ path = preprocessor;
+ sourceTree = "<group>";
+ };
+ FB39D2201200F35A00088E69 /* compiler */ = {
+ isa = PBXGroup;
+ children = (
+ FB39D2211200F35A00088E69 /* BaseTypes.h */,
+ FB39D2221200F35A00088E69 /* CodeGenGLSL.cpp */,
+ FB39D2241200F35A00088E69 /* Common.h */,
+ FB39D2251200F35A00088E69 /* ConstantUnion.h */,
+ FB39D2261200F35A00088E69 /* debug.cpp */,
+ FB39D2271200F35A00088E69 /* debug.h */,
+ FB39D2281200F35A00088E69 /* glslang.l */,
+ FB39D2291200F35A00088E69 /* glslang.y */,
+ FB39D22A1200F35A00088E69 /* InfoSink.cpp */,
+ FB39D22B1200F35A00088E69 /* InfoSink.h */,
+ FB39D22C1200F35A00088E69 /* Initialize.cpp */,
+ FB39D22D1200F35A00088E69 /* Initialize.h */,
+ FB39D22E1200F35A00088E69 /* InitializeDll.cpp */,
+ FB39D22F1200F35A00088E69 /* InitializeDll.h */,
+ FB39D2301200F35A00088E69 /* InitializeGlobals.h */,
+ FB39D2311200F35A00088E69 /* InitializeParseContext.h */,
+ FB39D2321200F35A00088E69 /* Intermediate.cpp */,
+ FB39D2331200F35A00088E69 /* intermediate.h */,
+ FB39D2341200F35A00088E69 /* intermOut.cpp */,
+ FB39D2351200F35A00088E69 /* IntermTraverse.cpp */,
+ FB39D2361200F35A00088E69 /* localintermediate.h */,
+ FB39D2371200F35A00088E69 /* MMap.h */,
+ FB39D2381200F35A00088E69 /* osinclude.h */,
+ FB39D2391200F35A00088E69 /* ossource_posix.cpp */,
+ FB39D23A1200F35A00088E69 /* ossource_win.cpp */,
+ FB39D23B1200F35A00088E69 /* OutputGLSL.cpp */,
+ FB39D23C1200F35A00088E69 /* OutputGLSL.h */,
+ FB39D23F1200F35A00088E69 /* parseConst.cpp */,
+ FB39D2401200F35A00088E69 /* ParseHelper.cpp */,
+ FB39D2411200F35A00088E69 /* ParseHelper.h */,
+ FB39D2421200F35A00088E69 /* PoolAlloc.cpp */,
+ FB39D2431200F35A00088E69 /* PoolAlloc.h */,
+ FB39D2441200F35A00088E69 /* preprocessor */,
+ FB39D2561200F35A00088E69 /* QualifierAlive.cpp */,
+ FB39D2571200F35A00088E69 /* QualifierAlive.h */,
+ FB39D2581200F35A00088E69 /* RemoveTree.cpp */,
+ FB39D2591200F35A00088E69 /* RemoveTree.h */,
+ FB39D25A1200F35A00088E69 /* ShaderLang.cpp */,
+ FB39D25B1200F35A00088E69 /* ShHandle.h */,
+ FB39D25C1200F35A00088E69 /* SymbolTable.cpp */,
+ FB39D25D1200F35A00088E69 /* SymbolTable.h */,
+ FB39D2681200F35A00088E69 /* TranslatorGLSL.cpp */,
+ FB39D2691200F35A00088E69 /* TranslatorGLSL.h */,
+ FB39D26C1200F35A00088E69 /* Types.h */,
+ FB39D26D1200F35A00088E69 /* UnfoldSelect.cpp */,
+ FB39D26E1200F35A00088E69 /* UnfoldSelect.h */,
+ FB39D26F1200F35A00088E69 /* unistd.h */,
+ );
+ name = compiler;
+ path = src/compiler;
+ sourceTree = "<group>";
+ };
+ FB39D2441200F35A00088E69 /* preprocessor */ = {
+ isa = PBXGroup;
+ children = (
+ FB39D2451200F35A00088E69 /* atom.c */,
+ FB39D2461200F35A00088E69 /* atom.h */,
+ FB39D2471200F35A00088E69 /* compile.h */,
+ FB39D2481200F35A00088E69 /* cpp.c */,
+ FB39D2491200F35A00088E69 /* cpp.h */,
+ FB39D24A1200F35A00088E69 /* cppstruct.c */,
+ FB39D24B1200F35A00088E69 /* memory.c */,
+ FB39D24C1200F35A00088E69 /* memory.h */,
+ FB39D24D1200F35A00088E69 /* parser.h */,
+ FB39D24E1200F35A00088E69 /* preprocess.h */,
+ FB39D24F1200F35A00088E69 /* scanner.c */,
+ FB39D2501200F35A00088E69 /* scanner.h */,
+ FB39D2511200F35A00088E69 /* slglobals.h */,
+ FB39D2521200F35A00088E69 /* symbols.c */,
+ FB39D2531200F35A00088E69 /* symbols.h */,
+ FB39D2541200F35A00088E69 /* tokens.c */,
+ FB39D2551200F35A00088E69 /* tokens.h */,
+ );
+ path = preprocessor;
+ sourceTree = "<group>";
+ };
+ FB39D2BD1200F3E600088E69 /* GLSLANG */ = {
+ isa = PBXGroup;
+ children = (
+ FB39D2BF1200F3E600088E69 /* ShaderLang.h */,
+ );
+ name = GLSLANG;
+ path = include/GLSLANG;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ FB39D77B1201110C00088E69 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ FB39D76E120110FC00088E69 /* ShaderLang.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ FB39D0D01200F0E300088E69 /* ANGLE */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = FB39D0D61200F11E00088E69 /* Build configuration list for PBXNativeTarget "ANGLE" */;
+ buildPhases = (
+ FB39D77B1201110C00088E69 /* Headers */,
+ FB39D0DE1200F19100088E69 /* Generate glslang lexer */,
+ FB39D31C1200F69200088E69 /* Generate glslang parser */,
+ FB39D0CE1200F0E300088E69 /* Sources */,
+ FB39D0CF1200F0E300088E69 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = ANGLE;
+ productName = angle;
+ productReference = FB39D0D11200F0E300088E69 /* libANGLE.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ FB39D0701200ED9200088E69 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = FB39D0731200ED9200088E69 /* Build configuration list for PBXProject "ANGLE" */;
+ compatibilityVersion = "Xcode 2.4";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
+ mainGroup = FB39D06E1200ED9200088E69;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ FB39D0D01200F0E300088E69 /* ANGLE */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ FB39D0DE1200F19100088E69 /* Generate glslang lexer */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 12;
+ files = (
+ );
+ inputPaths = (
+ "$(SRCROOT)/src/compiler/glslang.l",
+ );
+ name = "Generate glslang lexer";
+ outputPaths = (
+ "$(BUILT_PRODUCTS_DIR)/DerivedSources/$(PROJECT_NAME)/glslang.cpp",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "mkdir -p \"${BUILT_PRODUCTS_DIR}/DerivedSources/${PROJECT_NAME}\"\nflex --noline --nounistd \"--outfile=${BUILT_PRODUCTS_DIR}/DerivedSources/${PROJECT_NAME}/glslang.cpp\" \"${SRCROOT}/src/compiler/glslang.l\"\n";
+ };
+ FB39D31C1200F69200088E69 /* Generate glslang parser */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(SRCROOT)/src/compiler/glslang.y",
+ );
+ name = "Generate glslang parser";
+ outputPaths = (
+ "$(BUILT_PRODUCTS_DIR)/DerivedSources/$(PROJECT_NAME)/glslang_tab.cpp",
+ "$(BUILT_PRODUCTS_DIR)/DerivedSources/$(PROJECT_NAME)/glslang_tab.h",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "mkdir -p \"${BUILT_PRODUCTS_DIR}/DerivedSources/${PROJECT_NAME}\"\nbison --no-lines \"--defines=${BUILT_PRODUCTS_DIR}/DerivedSources/${PROJECT_NAME}/glslang_tab.h\" \"--skeleton=yacc.c\" \"--output=${BUILT_PRODUCTS_DIR}/DerivedSources/${PROJECT_NAME}/glslang_tab.cpp\" \"${SRCROOT}/src/compiler/glslang.y\"\n";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ FB39D0CE1200F0E300088E69 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ FB39D7231201032000088E69 /* glslang.cpp in Sources */,
+ FB39D7241201032000088E69 /* glslang_tab.cpp in Sources */,
+ FB39D2711200F35A00088E69 /* CodeGenGLSL.cpp in Sources */,
+ FB39D2751200F35A00088E69 /* debug.cpp in Sources */,
+ FB39D2791200F35A00088E69 /* InfoSink.cpp in Sources */,
+ FB39D27B1200F35A00088E69 /* Initialize.cpp in Sources */,
+ FB39D27D1200F35A00088E69 /* InitializeDll.cpp in Sources */,
+ FB39D2811200F35A00088E69 /* Intermediate.cpp in Sources */,
+ FB39D2831200F35A00088E69 /* intermOut.cpp in Sources */,
+ FB39D2841200F35A00088E69 /* IntermTraverse.cpp in Sources */,
+ FB39D2881200F35A00088E69 /* ossource_posix.cpp in Sources */,
+ FB39D28A1200F35A00088E69 /* OutputGLSL.cpp in Sources */,
+ FB39D28E1200F35A00088E69 /* parseConst.cpp in Sources */,
+ FB39D28F1200F35A00088E69 /* ParseHelper.cpp in Sources */,
+ FB39D2911200F35A00088E69 /* PoolAlloc.cpp in Sources */,
+ FB39D2931200F35A00088E69 /* atom.c in Sources */,
+ FB39D2961200F35A00088E69 /* cpp.c in Sources */,
+ FB39D2981200F35A00088E69 /* cppstruct.c in Sources */,
+ FB39D2991200F35A00088E69 /* memory.c in Sources */,
+ FB39D29D1200F35A00088E69 /* scanner.c in Sources */,
+ FB39D2A01200F35A00088E69 /* symbols.c in Sources */,
+ FB39D2A21200F35A00088E69 /* tokens.c in Sources */,
+ FB39D2A41200F35A00088E69 /* QualifierAlive.cpp in Sources */,
+ FB39D2A61200F35A00088E69 /* RemoveTree.cpp in Sources */,
+ FB39D2A81200F35A00088E69 /* ShaderLang.cpp in Sources */,
+ FB39D2AA1200F35A00088E69 /* SymbolTable.cpp in Sources */,
+ FB39D2AC1200F35A00088E69 /* TranslatorGLSL.cpp in Sources */,
+ FB39D2B11200F35A00088E69 /* UnfoldSelect.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 5D7C59DB1208C6C3001C873E /* Production */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 5D7C59C61208C68B001C873E /* Base.xcconfig */;
+ buildSettings = {
+ };
+ name = Production;
+ };
+ 5D7C59DC1208C6C3001C873E /* Production */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 5D7C59C51208C68B001C873E /* ANGLE.xcconfig */;
+ buildSettings = {
+ };
+ name = Production;
+ };
+ FB39D0711200ED9200088E69 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 5D7C59C71208C68B001C873E /* DebugRelease.xcconfig */;
+ buildSettings = {
+ GCC_OPTIMIZATION_LEVEL = 0;
+ };
+ name = Debug;
+ };
+ FB39D0721200ED9200088E69 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 5D7C59C71208C68B001C873E /* DebugRelease.xcconfig */;
+ buildSettings = {
+ };
+ name = Release;
+ };
+ FB39D0D21200F0E400088E69 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 5D7C59C51208C68B001C873E /* ANGLE.xcconfig */;
+ buildSettings = {
+ };
+ name = Debug;
+ };
+ FB39D0D31200F0E400088E69 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 5D7C59C51208C68B001C873E /* ANGLE.xcconfig */;
+ buildSettings = {
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ FB39D0731200ED9200088E69 /* Build configuration list for PBXProject "ANGLE" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ FB39D0711200ED9200088E69 /* Debug */,
+ FB39D0721200ED9200088E69 /* Release */,
+ 5D7C59DB1208C6C3001C873E /* Production */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Production;
+ };
+ FB39D0D61200F11E00088E69 /* Build configuration list for PBXNativeTarget "ANGLE" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ FB39D0D21200F0E400088E69 /* Debug */,
+ FB39D0D31200F0E400088E69 /* Release */,
+ 5D7C59DC1208C6C3001C873E /* Production */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Production;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = FB39D0701200ED9200088E69 /* Project object */;
+}
diff --git a/Source/ThirdParty/ANGLE/ChangeLog b/Source/ThirdParty/ANGLE/ChangeLog
new file mode 100644
index 0000000..4246845
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/ChangeLog
@@ -0,0 +1,582 @@
+2010-12-01 Steve Falkenburg <sfalken@apple.com>
+
+ Reviewed by Adam Roben.
+
+ vcproj changes can't be applied cleanly by the Windows EWS bot
+ https://bugs.webkit.org/show_bug.cgi?id=50328
+
+ * src/libEGL/libEGL.vcproj: Added property svn:eol-style.
+ * src/libGLESv2/libGLESv2.vcproj: Added property svn:eol-style.
+
+2010-11-03 Darin Adler <darin@apple.com>
+
+ Updated Xcode projects by opening them with Xcode 3.2.4.
+ Updated svn:ignore for Xcode projects.
+
+ * ANGLE.xcodeproj: Added property svn:ignore.
+ * ANGLE.xcodeproj/project.pbxproj: Updated with Xcode 3.2.4.
+ * src/build_angle.xcodeproj: Added property svn:ignore.
+ * src/build_angle.xcodeproj/project.pbxproj: Updated with Xcode 3.2.4.
+
+2010-09-01 Zhenyao Mo <zmo@google.com>
+
+ Reviewed by Kenneth Russell.
+
+ Roll ANGLE under webkit to r402
+ https://bugs.webkit.org/show_bug.cgi?id=45004
+
+ * ANGLE.xcodeproj/project.pbxproj:
+ * include/GLES2/gl2ext.h:
+ * include/GLSLANG/ResourceLimits.h: Removed.
+ * include/GLSLANG/ShaderLang.h:
+ * src/compiler/BaseTypes.h:
+ (getPrecisionString):
+ (getBasicString):
+ (IsSampler):
+ (getQualifierString):
+ * src/compiler/Initialize.cpp:
+ (BuiltInConstants):
+ (IdentifyBuiltIns):
+ * src/compiler/Initialize.h:
+ * src/compiler/InitializeDll.cpp:
+ (InitProcess):
+ (DetachProcess):
+ (InitThread):
+ (DetachThread):
+ * src/compiler/InitializeDll.h:
+ * src/compiler/InitializeParseContext.h:
+ * src/compiler/Intermediate.cpp:
+ (GetHigherPrecision):
+ (TIntermediate::addBinaryMath):
+ (TIntermediate::setAggregateOperator):
+ (TIntermediate::addComma):
+ (TIntermediate::postProcess):
+ (TIntermBinary::promote):
+ (CompareStruct):
+ * src/compiler/OutputGLSL.cpp:
+ (TOutputGLSL::writeFunctionParameters):
+ (TOutputGLSL::visitUnary):
+ (TOutputGLSL::visitBranch):
+ * src/compiler/OutputHLSL.cpp:
+ (sh::OutputHLSL::header):
+ (sh::OutputHLSL::visitBinary):
+ (sh::OutputHLSL::visitAggregate):
+ (sh::OutputHLSL::handleExcessiveLoop):
+ (sh::OutputHLSL::addConstructor):
+ * src/compiler/ParseHelper.cpp:
+ (TParseContext::constructorErrorCheck):
+ (TParseContext::samplerErrorCheck):
+ (TParseContext::paramErrorCheck):
+ (TParseContext::findFunction):
+ (TParseContext::executeInitializer):
+ (TParseContext::addConstructor):
+ (TParseContext::addConstStruct):
+ (FreeParseContextIndex):
+ (GetGlobalParseContext):
+ * src/compiler/PoolAlloc.h:
+ (TPoolAllocator::tHeader::tHeader):
+ (pool_allocator::allocate):
+ (pool_allocator::deallocate):
+ * src/compiler/ShaderLang.cpp:
+ (ShInitialize):
+ (ShFinalize):
+ (ShInitBuiltInResource):
+ * src/compiler/SymbolTable.cpp:
+ (TType::getStructSize):
+ * src/compiler/SymbolTable.h:
+ (TVariable::setQualifier):
+ * src/compiler/Types.h:
+ (TType::TType):
+ (TType::getBasicType):
+ (TType::setBasicType):
+ (TType::getPrecision):
+ (TType::setPrecision):
+ (TType::getQualifier):
+ (TType::setQualifier):
+ (TType::getNominalSize):
+ (TType::setNominalSize):
+ (TType::isMatrix):
+ (TType::setMatrix):
+ (TType::isArray):
+ (TType::getArraySize):
+ (TType::setArraySize):
+ (TType::getMaxArraySize):
+ (TType::setMaxArraySize):
+ (TType::clearArrayness):
+ (TType::setArrayInformationType):
+ (TType::getArrayInformationType):
+ (TType::isVector):
+ (TType::isScalar):
+ (TType::setStruct):
+ (TType::getTypeName):
+ (TType::setTypeName):
+ (TType::isField):
+ (TType::getFieldName):
+ (TType::setFieldName):
+ (TType::getBasicString):
+ (TType::getPrecisionString):
+ (TType::getQualifierString):
+ * src/compiler/glslang.l:
+ * src/compiler/glslang.y:
+ * src/compiler/intermediate.h:
+ (TIntermNode::getLine):
+ (TIntermNode::setLine):
+ (TIntermTyped::getAsTyped):
+ (TIntermTyped::setType):
+ (TIntermTyped::getType):
+ (TIntermTyped::getTypePointer):
+ (TIntermTyped::getBasicType):
+ (TIntermTyped::getQualifier):
+ (TIntermTyped::getPrecision):
+ (TIntermTyped::getNominalSize):
+ (TIntermTyped::isMatrix):
+ (TIntermTyped::isArray):
+ (TIntermTyped::isVector):
+ (TIntermTyped::isScalar):
+ (TIntermTyped::getBasicString):
+ (TIntermTyped::getQualifierString):
+ (TIntermSymbol::getId):
+ (TIntermSymbol::getSymbol):
+ (TIntermOperator::setOp):
+ (TIntermBinary::setLeft):
+ (TIntermBinary::setRight):
+ (TIntermBinary::getLeft):
+ (TIntermBinary::getRight):
+ (TIntermUnary::setOperand):
+ (TIntermUnary::getOperand):
+ (TIntermAggregate::getAsAggregate):
+ (TIntermAggregate::getSequence):
+ (TIntermAggregate::setName):
+ (TIntermAggregate::getName):
+ (TIntermAggregate::setUserDefined):
+ (TIntermAggregate::isUserDefined):
+ (TIntermAggregate::getQualifier):
+ (TIntermAggregate::setOptimize):
+ (TIntermAggregate::setDebug):
+ (TIntermSelection::getCondition):
+ (TIntermSelection::getTrueBlock):
+ (TIntermSelection::getFalseBlock):
+ (TIntermSelection::getAsSelectionNode):
+ * src/compiler/parseConst.cpp:
+ (TConstTraverser::TConstTraverser):
+ * src/compiler/preprocessor/atom.c:
+ (InitAtomTable):
+ * src/compiler/preprocessor/atom.h:
+ * src/compiler/preprocessor/compile.h:
+ * src/compiler/preprocessor/cpp.c:
+ * src/compiler/preprocessor/cpp.h:
+ * src/compiler/preprocessor/cppstruct.c:
+ * src/compiler/preprocessor/memory.c:
+ * src/compiler/preprocessor/memory.h:
+ * src/compiler/preprocessor/parser.h:
+ * src/compiler/preprocessor/preprocess.h:
+ * src/compiler/preprocessor/scanner.c:
+ * src/compiler/preprocessor/scanner.h:
+ * src/compiler/preprocessor/slglobals.h:
+ * src/compiler/preprocessor/symbols.c:
+ (NewSymbol):
+ * src/compiler/preprocessor/symbols.h:
+ * src/compiler/preprocessor/tokens.c:
+ (RecordToken):
+ * src/compiler/preprocessor/tokens.h:
+ * src/libEGL/Display.cpp:
+ (egl::Display::Display):
+ (egl::Display::initialize):
+ (egl::Display::terminate):
+ (egl::Display::createDevice):
+ (egl::Display::createWindowSurface):
+ (egl::Display::createContext):
+ (egl::Display::getMultiSampleSupport):
+ (egl::Display::getCompressedTextureSupport):
+ * src/libEGL/Display.h:
+ * src/libEGL/Surface.cpp:
+ (egl::Surface::Surface):
+ (egl::Surface::resetSwapChain):
+ (egl::Surface::getWindowHandle):
+ (egl::Surface::writeRecordableFlipState):
+ (egl::Surface::applyFlipState):
+ (egl::Surface::releaseRecordedState):
+ (egl::Surface::checkForWindowResize):
+ (egl::Surface::swap):
+ * src/libEGL/Surface.h:
+ * src/libEGL/libEGL.cpp:
+ * src/libEGL/libEGL.vcproj:
+ * src/libGLESv2/Blit.cpp:
+ (gl::Blit::setVertexShader):
+ (gl::Blit::setPixelShader):
+ (gl::Blit::setFormatConvertShaders):
+ * src/libGLESv2/Buffer.cpp:
+ (gl::Buffer::Buffer):
+ * src/libGLESv2/Buffer.h:
+ * src/libGLESv2/Context.cpp:
+ (gl::Context::Context):
+ (gl::Context::~Context):
+ (gl::Context::makeCurrent):
+ (gl::Context::markAllStateDirty):
+ (gl::Context::getReadFramebufferHandle):
+ (gl::Context::getDrawFramebufferHandle):
+ (gl::Context::getRenderbufferHandle):
+ (gl::Context::getArrayBufferHandle):
+ (gl::Context::setVertexAttribState):
+ (gl::Context::createBuffer):
+ (gl::Context::createProgram):
+ (gl::Context::createShader):
+ (gl::Context::createTexture):
+ (gl::Context::createRenderbuffer):
+ (gl::Context::deleteBuffer):
+ (gl::Context::deleteShader):
+ (gl::Context::deleteProgram):
+ (gl::Context::deleteTexture):
+ (gl::Context::deleteRenderbuffer):
+ (gl::Context::getBuffer):
+ (gl::Context::getShader):
+ (gl::Context::getProgram):
+ (gl::Context::getTexture):
+ (gl::Context::getRenderbuffer):
+ (gl::Context::getReadFramebuffer):
+ (gl::Context::getDrawFramebuffer):
+ (gl::Context::bindArrayBuffer):
+ (gl::Context::bindElementArrayBuffer):
+ (gl::Context::bindTexture2D):
+ (gl::Context::bindTextureCubeMap):
+ (gl::Context::bindReadFramebuffer):
+ (gl::Context::bindDrawFramebuffer):
+ (gl::Context::bindRenderbuffer):
+ (gl::Context::useProgram):
+ (gl::Context::setFramebufferZero):
+ (gl::Context::setRenderbufferStorage):
+ (gl::Context::getFramebuffer):
+ (gl::Context::getArrayBuffer):
+ (gl::Context::getElementArrayBuffer):
+ (gl::Context::getCurrentProgram):
+ (gl::Context::getTexture2D):
+ (gl::Context::getTextureCubeMap):
+ (gl::Context::getSamplerTexture):
+ (gl::Context::getFloatv):
+ (gl::Context::getIntegerv):
+ (gl::Context::getQueryParameterInfo):
+ (gl::Context::applyRenderTarget):
+ (gl::Context::applyState):
+ (gl::Context::applyIndexBuffer):
+ (gl::Context::readPixels):
+ (gl::Context::clear):
+ (gl::Context::finish):
+ (gl::Context::flush):
+ (gl::Context::supportsShaderModel3):
+ (gl::Context::getMaxSupportedSamples):
+ (gl::Context::getNearestSupportedSamples):
+ (gl::Context::supportsCompressedTextures):
+ (gl::Context::detachBuffer):
+ (gl::Context::detachTexture):
+ (gl::Context::detachFramebuffer):
+ (gl::Context::detachRenderbuffer):
+ (gl::Context::getIncompleteTexture):
+ (gl::Context::initExtensionString):
+ (gl::Context::blitFramebuffer):
+ * src/libGLESv2/Context.h:
+ (gl::AttributeState::AttributeState):
+ * src/libGLESv2/Framebuffer.cpp:
+ (gl::Framebuffer::Framebuffer):
+ (gl::Framebuffer::~Framebuffer):
+ (gl::Framebuffer::lookupRenderbuffer):
+ (gl::Framebuffer::setColorbuffer):
+ (gl::Framebuffer::setDepthbuffer):
+ (gl::Framebuffer::setStencilbuffer):
+ (gl::Framebuffer::detachTexture):
+ (gl::Framebuffer::detachRenderbuffer):
+ (gl::Framebuffer::getRenderTargetSerial):
+ (gl::Framebuffer::getRenderTarget):
+ (gl::Framebuffer::getDepthStencil):
+ (gl::Framebuffer::getDepthbufferSerial):
+ (gl::Framebuffer::getStencilbufferSerial):
+ (gl::Framebuffer::getColorbuffer):
+ (gl::Framebuffer::getDepthbuffer):
+ (gl::Framebuffer::getStencilbuffer):
+ (gl::Framebuffer::getColorbufferHandle):
+ (gl::Framebuffer::getDepthbufferHandle):
+ (gl::Framebuffer::getStencilbufferHandle):
+ (gl::Framebuffer::hasStencil):
+ (gl::Framebuffer::isMultisample):
+ (gl::Framebuffer::completeness):
+ (gl::DefaultFramebuffer::DefaultFramebuffer):
+ (gl::Framebuffer::getSamples):
+ (gl::DefaultFramebuffer::completeness):
+ * src/libGLESv2/Framebuffer.h:
+ * src/libGLESv2/Program.cpp:
+ (gl::Program::Program):
+ (gl::Program::~Program):
+ (gl::Program::attachShader):
+ (gl::Program::detachShader):
+ (gl::Program::linkVaryings):
+ (gl::Program::link):
+ (gl::Program::unlink):
+ (gl::Program::release):
+ (gl::Program::addRef):
+ (gl::Program::getRefCount):
+ (gl::Program::getDxViewportLocation):
+ * src/libGLESv2/Program.h:
+ * src/libGLESv2/RefCountObject.cpp: Added.
+ (gl::RefCountObject::RefCountObject):
+ (gl::RefCountObject::~RefCountObject):
+ (gl::RefCountObject::addRef):
+ (gl::RefCountObject::release):
+ (gl::RefCountObjectBindingPointer::set):
+ * src/libGLESv2/RefCountObject.h: Added.
+ (gl::RefCountObject::id):
+ (gl::RefCountObjectBindingPointer::RefCountObjectBindingPointer):
+ (gl::RefCountObjectBindingPointer::~RefCountObjectBindingPointer):
+ (gl::RefCountObjectBindingPointer::get):
+ (gl::RefCountObjectBindingPointer::id):
+ (gl::RefCountObjectBindingPointer::operator ! ):
+ (gl::BindingPointer::set):
+ (gl::BindingPointer::get):
+ (gl::BindingPointer::operator -> ):
+ * src/libGLESv2/Renderbuffer.cpp:
+ (gl::Renderbuffer::Renderbuffer):
+ (gl::Renderbuffer::~Renderbuffer):
+ (gl::Renderbuffer::isColorbuffer):
+ (gl::Renderbuffer::isDepthbuffer):
+ (gl::Renderbuffer::isStencilbuffer):
+ (gl::Renderbuffer::getRenderTarget):
+ (gl::Renderbuffer::getDepthStencil):
+ (gl::Renderbuffer::getWidth):
+ (gl::Renderbuffer::getHeight):
+ (gl::Renderbuffer::getFormat):
+ (gl::Renderbuffer::getD3DFormat):
+ (gl::Renderbuffer::getSerial):
+ (gl::Renderbuffer::setStorage):
+ (gl::RenderbufferStorage::RenderbufferStorage):
+ (gl::RenderbufferStorage::~RenderbufferStorage):
+ (gl::RenderbufferStorage::isColorbuffer):
+ (gl::RenderbufferStorage::isDepthbuffer):
+ (gl::RenderbufferStorage::isStencilbuffer):
+ (gl::RenderbufferStorage::getRenderTarget):
+ (gl::RenderbufferStorage::getDepthStencil):
+ (gl::RenderbufferStorage::getWidth):
+ (gl::RenderbufferStorage::getHeight):
+ (gl::RenderbufferStorage::setSize):
+ (gl::RenderbufferStorage::getFormat):
+ (gl::RenderbufferStorage::getD3DFormat):
+ (gl::RenderbufferStorage::getSamples):
+ (gl::RenderbufferStorage::getSerial):
+ (gl::RenderbufferStorage::issueSerial):
+ (gl::Colorbuffer::Colorbuffer):
+ (gl::Colorbuffer::isColorbuffer):
+ (gl::Colorbuffer::getRedSize):
+ (gl::Colorbuffer::getGreenSize):
+ (gl::Colorbuffer::getBlueSize):
+ (gl::Colorbuffer::getAlphaSize):
+ (gl::DepthStencilbuffer::DepthStencilbuffer):
+ (gl::DepthStencilbuffer::~DepthStencilbuffer):
+ (gl::DepthStencilbuffer::isDepthbuffer):
+ (gl::DepthStencilbuffer::isStencilbuffer):
+ (gl::DepthStencilbuffer::getDepthSize):
+ (gl::DepthStencilbuffer::getStencilSize):
+ (gl::DepthStencilbuffer::getDepthStencil):
+ (gl::Depthbuffer::Depthbuffer):
+ (gl::Depthbuffer::~Depthbuffer):
+ (gl::Depthbuffer::isDepthbuffer):
+ (gl::Depthbuffer::isStencilbuffer):
+ (gl::Stencilbuffer::Stencilbuffer):
+ (gl::Stencilbuffer::~Stencilbuffer):
+ (gl::Stencilbuffer::isDepthbuffer):
+ (gl::Stencilbuffer::isStencilbuffer):
+ * src/libGLESv2/Renderbuffer.h:
+ (gl::Renderbuffer::getStorage):
+ * src/libGLESv2/ResourceManager.cpp: Added.
+ (gl::ResourceManager::ResourceManager):
+ (gl::ResourceManager::~ResourceManager):
+ (gl::ResourceManager::addRef):
+ (gl::ResourceManager::release):
+ (gl::ResourceManager::createBuffer):
+ (gl::ResourceManager::createShader):
+ (gl::ResourceManager::createProgram):
+ (gl::ResourceManager::createTexture):
+ (gl::ResourceManager::createRenderbuffer):
+ (gl::ResourceManager::deleteBuffer):
+ (gl::ResourceManager::deleteShader):
+ (gl::ResourceManager::deleteProgram):
+ (gl::ResourceManager::deleteTexture):
+ (gl::ResourceManager::deleteRenderbuffer):
+ (gl::ResourceManager::getBuffer):
+ (gl::ResourceManager::getShader):
+ (gl::ResourceManager::getTexture):
+ (gl::ResourceManager::getProgram):
+ (gl::ResourceManager::getRenderbuffer):
+ (gl::ResourceManager::setRenderbuffer):
+ (gl::ResourceManager::checkBufferAllocation):
+ (gl::ResourceManager::checkTextureAllocation):
+ (gl::ResourceManager::checkRenderbufferAllocation):
+ * src/libGLESv2/ResourceManager.h: Added.
+ * src/libGLESv2/Shader.cpp:
+ (gl::Shader::Shader):
+ (gl::Shader::addRef):
+ (gl::Shader::release):
+ (gl::Shader::getRefCount):
+ (gl::Shader::parseVaryings):
+ (gl::VertexShader::VertexShader):
+ (gl::FragmentShader::FragmentShader):
+ * src/libGLESv2/Shader.h:
+ * src/libGLESv2/Texture.cpp:
+ (gl::Texture::Image::Image):
+ (gl::Texture::Texture):
+ (gl::Texture::getBlitter):
+ (gl::Texture::selectFormat):
+ (gl::Texture::loadImageData):
+ (gl::Texture::loadAlphaImageData):
+ (gl::Texture::loadLuminanceImageData):
+ (gl::Texture::loadLuminanceAlphaImageData):
+ (gl::Texture::loadRGBUByteImageData):
+ (gl::Texture::loadRGB565ImageData):
+ (gl::Texture::loadRGBAUByteImageData):
+ (gl::Texture::loadRGBA4444ImageData):
+ (gl::Texture::loadRGBA5551ImageData):
+ (gl::Texture::loadBGRAImageData):
+ (gl::Texture::createSurface):
+ (gl::Texture::setImage):
+ (gl::Texture::setCompressedImage):
+ (gl::Texture::subImage):
+ (gl::Texture::subImageCompressed):
+ (gl::Texture2D::Texture2D):
+ (gl::Texture2D::getFormat):
+ (gl::Texture2D::setCompressedImage):
+ (gl::Texture2D::subImage):
+ (gl::Texture2D::subImageCompressed):
+ (gl::Texture2D::copyImage):
+ (gl::Texture2D::copySubImage):
+ (gl::Texture2D::isCompressed):
+ (gl::Texture2D::getColorbuffer):
+ (gl::TextureCubeMap::TextureCubeMap):
+ (gl::TextureCubeMap::getFormat):
+ (gl::TextureCubeMap::setCompressedImage):
+ (gl::TextureCubeMap::subImage):
+ (gl::TextureCubeMap::subImageCompressed):
+ (gl::TextureCubeMap::isCompressed):
+ (gl::TextureCubeMap::copyImage):
+ (gl::TextureCubeMap::copySubImage):
+ (gl::TextureCubeMap::getColorbuffer):
+ (gl::Texture::TextureColorbufferProxy::addRef):
+ (gl::Texture::TextureColorbufferProxy::release):
+ (gl::Texture::TextureColorbufferProxy::getWidth):
+ (gl::Texture::TextureColorbufferProxy::getHeight):
+ (gl::Texture::TextureColorbufferProxy::getFormat):
+ * src/libGLESv2/Texture.h:
+ * src/libGLESv2/libGLESv2.cpp:
+ * src/libGLESv2/libGLESv2.def:
+ * src/libGLESv2/libGLESv2.vcproj:
+ * src/libGLESv2/main.h:
+ * src/libGLESv2/utilities.cpp:
+ (gl::ComputeCompressedPitch):
+ (gl::ComputeCompressedSize):
+ (gl::IsCompressed):
+ (gl::ComputePixelSize):
+ (gl::CheckTextureFormatType):
+ (es2dx::ConvertRenderbufferFormat):
+ (es2dx::GetSamplesFromMultisampleType):
+ (es2dx::GetMultisampleTypeFromSamples):
+ * src/libGLESv2/utilities.h:
+
+2010-08-17 Chris Marrin <cmarrin@apple.com>
+
+ Unreviewed.
+
+ Moved previous link error fix to Base.xcconfig.
+
+ * ANGLE.xcodeproj/project.pbxproj:
+ * Configurations/Base.xcconfig:
+
+2010-08-17 Chris Marrin <cmarrin@apple.com>
+
+ Unreviewed.
+
+ Got rid of link errors in WebCore.
+
+ Changed GCC_INLINES_ARE_PRIVATE_EXTERN to YES and
+ GCC_SYMBOLS_PRIVATE_EXTERN to NO to match WebCore
+ flags.
+
+ * ANGLE.xcodeproj/project.pbxproj:
+
+2010-08-04 Kenneth Russell <kbr@google.com>
+
+ Reviewed by Dimitri Glazkov.
+
+ Update ANGLE to r352
+ https://bugs.webkit.org/show_bug.cgi?id=43500
+
+ Updated ANGLE to r352 (July 26, 2010). Built WebKit to test.
+
+ * include/GLSLANG/ShaderLang.h:
+ * src/compiler/Initialize.cpp:
+ (BuiltInFunctionsCommon):
+ (BuiltInFunctionsVertex):
+ (BuiltInFunctionsFragment):
+ (StandardUniforms):
+ (DefaultPrecisionVertex):
+ (DefaultPrecisionFragment):
+ (BuiltInConstants):
+ (TBuiltIns::initialize):
+ (IdentifyBuiltIns):
+ * src/compiler/Initialize.h:
+ (TBuiltIns::getBuiltInStrings):
+ * src/compiler/OutputGLSL.cpp:
+ (TOutputGLSL::visitSelection):
+ * src/compiler/ShHandle.h:
+ (TCompiler::getLanguage):
+ (TCompiler::getSpec):
+ (TCompiler::getSymbolTable):
+ (TCompiler::getInfoSink):
+ * src/compiler/ShaderLang.cpp:
+ (InitializeSymbolTable):
+ (GenerateBuiltInSymbolTable):
+ (ShInitialize):
+ (ShConstructCompiler):
+ (ShFinalize):
+ (ShCompile):
+ * src/compiler/SymbolTable.h:
+ (TSymbolTable::atBuiltInLevel):
+ (TSymbolTable::atGlobalLevel):
+ (TSymbolTable::push):
+ (TSymbolTable::getGlobalLevel):
+ (TSymbolTable::currentLevel):
+ * src/libGLESv2/Shader.cpp:
+ (gl::Shader::Shader):
+ (gl::Shader::compileToHLSL):
+
+2010-08-03 Mark Rowe <mrowe@apple.com>
+
+ Rubber-stamped by Adele Peterson.
+
+ Remove some unnecessary files from the ANGLE tree.
+
+ * src/compiler/tools/COPYING.bison: Removed.
+ * src/compiler/tools/COPYING.flex: Removed.
+ * src/compiler/tools/README: Removed.
+ * src/compiler/tools/bison.hairy: Removed.
+ * src/compiler/tools/bison.simple: Removed.
+
+2010-08-03 Mark Rowe <mrowe@apple.com>
+
+ Rubber-stamped by Adele Peterson.
+
+ Clean up the ANGLE Xcode project.
+
+ Main changes include:
+ • Adding a Production configuration.
+ • Modifying the library name from libangle.a to libANGLE.a.
+ • Installing the headers in a subdirectory of /usr/local/include to avoid polluting the top-level directory.
+ • Generating derived sources in to the built products directory so they're saved along with the symroot.
+ • Switching to using .xcconfig files for maximum cleanliness.
+
+ * ANGLE.xcodeproj/project.pbxproj:
+ * Configurations/ANGLE.xcconfig: Added.
+ * Configurations/Base.xcconfig: Added.
+ * Configurations/DebugRelease.xcconfig: Added.
+
+2010-08-02 Paul Sawaya <psawaya@apple.com>
+
+ Reviewed by Adele Peterson.
+
+ Add ANGLE library to WebKit. From the repository (http://angleproject.googlecode.com) as of July 22.
+ https://bugs.webkit.org/show_bug.cgi?id=42789
+
diff --git a/Source/ThirdParty/ANGLE/Configurations/ANGLE.xcconfig b/Source/ThirdParty/ANGLE/Configurations/ANGLE.xcconfig
new file mode 100644
index 0000000..644b71d
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/Configurations/ANGLE.xcconfig
@@ -0,0 +1,5 @@
+PRODUCT_NAME = ANGLE;
+
+HEADER_SEARCH_PATHS = include src;
+INSTALL_PATH = /usr/local/lib;
+PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/ANGLE;
diff --git a/Source/ThirdParty/ANGLE/Configurations/Base.xcconfig b/Source/ThirdParty/ANGLE/Configurations/Base.xcconfig
new file mode 100644
index 0000000..e890e3b
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/Configurations/Base.xcconfig
@@ -0,0 +1,54 @@
+DEAD_CODE_STRIPPING = YES;
+DEBUG_INFORMATION_FORMAT = dwarf;
+GCC_C_LANGUAGE_STANDARD = gnu99;
+GCC_DEBUGGING_SYMBOLS = default;
+GCC_ENABLE_CPP_EXCEPTIONS = NO;
+GCC_ENABLE_CPP_RTTI = NO;
+GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+GCC_ENABLE_OBJC_GC = supported;
+GCC_ENABLE_SYMBOL_SEPARATION = NO;
+GCC_FAST_OBJC_DISPATCH = YES;
+GCC_MODEL_TUNING = G5;
+GCC_OBJC_CALL_CXX_CDTORS = YES;
+GCC_OPTIMIZATION_LEVEL = s;
+GCC_PRECOMPILE_PREFIX_HEADER = NO;
+GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
+GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+GCC_THREADSAFE_STATICS = NO;
+GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
+LINKER_DISPLAYS_MANGLED_NAMES = YES;
+PREBINDING = NO;
+STRIP_INSTALLED_PRODUCT = NO;
+
+
+TARGET_MAC_OS_X_VERSION_MAJOR = $(MAC_OS_X_VERSION_MAJOR);
+
+
+// Use GCC 4.2 with Xcode 3.1, which includes GCC 4.2 but defaults to GCC 4.0.
+// Note that Xcode versions as new as 3.1.2 use XCODE_VERSION_ACTUAL for the minor version
+// number. Newer versions of Xcode use XCODE_VERSION_MINOR for the minor version, and
+// XCODE_VERSION_ACTUAL for the full version number.
+TARGET_GCC_VERSION = $(TARGET_GCC_VERSION_$(TARGET_MAC_OS_X_VERSION_MAJOR));
+TARGET_GCC_VERSION_ = $(TARGET_GCC_VERSION_1040);
+TARGET_GCC_VERSION_1040 = GCC_40;
+TARGET_GCC_VERSION_1050 = $(TARGET_GCC_VERSION_1050_$(XCODE_VERSION_MINOR));
+TARGET_GCC_VERSION_1050_ = $(TARGET_GCC_VERSION_1050_$(XCODE_VERSION_ACTUAL));
+TARGET_GCC_VERSION_1050_0310 = GCC_42;
+TARGET_GCC_VERSION_1050_0320 = GCC_42;
+TARGET_GCC_VERSION_1060 = GCC_42;
+TARGET_GCC_VERSION_1070 = LLVM_GCC_42;
+
+GCC_VERSION = $(GCC_VERSION_$(TARGET_GCC_VERSION));
+GCC_VERSION_GCC_40 = 4.0;
+GCC_VERSION_GCC_42 = 4.2;
+GCC_VERSION_LLVM_GCC_42 = com.apple.compilers.llvmgcc42;
+
+// If the target Mac OS X version does not match the current Mac OS X version then we'll want to build using the target version's SDK.
+SDKROOT = $(SDKROOT_$(MAC_OS_X_VERSION_MAJOR)_$(TARGET_MAC_OS_X_VERSION_MAJOR));
+SDKROOT_1050_1040 = macosx10.4internal;
+SDKROOT_1060_1040 = macosx10.4internal;
+SDKROOT_1060_1050 = macosx10.5internal;
+SDKROOT_1070_1040 = macosx10.4internal;
+SDKROOT_1070_1050 = macosx10.5internal;
+SDKROOT_1070_1060 = macosx10.6internal;
diff --git a/Source/ThirdParty/ANGLE/Configurations/DebugRelease.xcconfig b/Source/ThirdParty/ANGLE/Configurations/DebugRelease.xcconfig
new file mode 100644
index 0000000..2d92931
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/Configurations/DebugRelease.xcconfig
@@ -0,0 +1,19 @@
+#include "Base.xcconfig"
+
+ARCHS = $(ARCHS_$(TARGET_MAC_OS_X_VERSION_MAJOR));
+ARCHS_ = $(ARCHS_1040);
+ARCHS_1040 = $(NATIVE_ARCH);
+ARCHS_1050 = $(NATIVE_ARCH);
+ARCHS_1060 = $(ARCHS_STANDARD_32_64_BIT);
+ARCHS_1070 = $(ARCHS_STANDARD_32_64_BIT);
+
+ONLY_ACTIVE_ARCH = YES;
+
+MACOSX_DEPLOYMENT_TARGET = $(MACOSX_DEPLOYMENT_TARGET_$(TARGET_MAC_OS_X_VERSION_MAJOR));
+MACOSX_DEPLOYMENT_TARGET_ = 10.4;
+MACOSX_DEPLOYMENT_TARGET_1040 = 10.4;
+MACOSX_DEPLOYMENT_TARGET_1050 = 10.5;
+MACOSX_DEPLOYMENT_TARGET_1060 = 10.6;
+MACOSX_DEPLOYMENT_TARGET_1070 = 10.7;
+
+GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES;
diff --git a/Source/ThirdParty/ANGLE/Makefile b/Source/ThirdParty/ANGLE/Makefile
new file mode 100644
index 0000000..cb4c11a
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/Makefile
@@ -0,0 +1 @@
+include ../Makefile.shared
diff --git a/Source/ThirdParty/ANGLE/include/EGL/egl.h b/Source/ThirdParty/ANGLE/include/EGL/egl.h
new file mode 100644
index 0000000..99ea342
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/include/EGL/egl.h
@@ -0,0 +1,329 @@
+/* -*- mode: c; tab-width: 8; -*- */
+/* vi: set sw=4 ts=8: */
+/* Reference version of egl.h for EGL 1.4.
+ * $Revision: 9356 $ on $Date: 2009-10-21 02:52:25 -0700 (Wed, 21 Oct 2009) $
+ */
+
+/*
+** Copyright (c) 2007-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+#ifndef __egl_h_
+#define __egl_h_
+
+/* All platform-dependent types and macro boilerplate (such as EGLAPI
+ * and EGLAPIENTRY) should go in eglplatform.h.
+ */
+#include <EGL/eglplatform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* EGL Types */
+/* EGLint is defined in eglplatform.h */
+typedef unsigned int EGLBoolean;
+typedef unsigned int EGLenum;
+typedef void *EGLConfig;
+typedef void *EGLContext;
+typedef void *EGLDisplay;
+typedef void *EGLSurface;
+typedef void *EGLClientBuffer;
+
+/* EGL Versioning */
+#define EGL_VERSION_1_0 1
+#define EGL_VERSION_1_1 1
+#define EGL_VERSION_1_2 1
+#define EGL_VERSION_1_3 1
+#define EGL_VERSION_1_4 1
+
+/* EGL Enumerants. Bitmasks and other exceptional cases aside, most
+ * enums are assigned unique values starting at 0x3000.
+ */
+
+/* EGL aliases */
+#define EGL_FALSE 0
+#define EGL_TRUE 1
+
+/* Out-of-band handle values */
+#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0)
+#define EGL_NO_CONTEXT ((EGLContext)0)
+#define EGL_NO_DISPLAY ((EGLDisplay)0)
+#define EGL_NO_SURFACE ((EGLSurface)0)
+
+/* Out-of-band attribute value */
+#define EGL_DONT_CARE ((EGLint)-1)
+
+/* Errors / GetError return values */
+#define EGL_SUCCESS 0x3000
+#define EGL_NOT_INITIALIZED 0x3001
+#define EGL_BAD_ACCESS 0x3002
+#define EGL_BAD_ALLOC 0x3003
+#define EGL_BAD_ATTRIBUTE 0x3004
+#define EGL_BAD_CONFIG 0x3005
+#define EGL_BAD_CONTEXT 0x3006
+#define EGL_BAD_CURRENT_SURFACE 0x3007
+#define EGL_BAD_DISPLAY 0x3008
+#define EGL_BAD_MATCH 0x3009
+#define EGL_BAD_NATIVE_PIXMAP 0x300A
+#define EGL_BAD_NATIVE_WINDOW 0x300B
+#define EGL_BAD_PARAMETER 0x300C
+#define EGL_BAD_SURFACE 0x300D
+#define EGL_CONTEXT_LOST 0x300E /* EGL 1.1 - IMG_power_management */
+
+/* Reserved 0x300F-0x301F for additional errors */
+
+/* Config attributes */
+#define EGL_BUFFER_SIZE 0x3020
+#define EGL_ALPHA_SIZE 0x3021
+#define EGL_BLUE_SIZE 0x3022
+#define EGL_GREEN_SIZE 0x3023
+#define EGL_RED_SIZE 0x3024
+#define EGL_DEPTH_SIZE 0x3025
+#define EGL_STENCIL_SIZE 0x3026
+#define EGL_CONFIG_CAVEAT 0x3027
+#define EGL_CONFIG_ID 0x3028
+#define EGL_LEVEL 0x3029
+#define EGL_MAX_PBUFFER_HEIGHT 0x302A
+#define EGL_MAX_PBUFFER_PIXELS 0x302B
+#define EGL_MAX_PBUFFER_WIDTH 0x302C
+#define EGL_NATIVE_RENDERABLE 0x302D
+#define EGL_NATIVE_VISUAL_ID 0x302E
+#define EGL_NATIVE_VISUAL_TYPE 0x302F
+#define EGL_SAMPLES 0x3031
+#define EGL_SAMPLE_BUFFERS 0x3032
+#define EGL_SURFACE_TYPE 0x3033
+#define EGL_TRANSPARENT_TYPE 0x3034
+#define EGL_TRANSPARENT_BLUE_VALUE 0x3035
+#define EGL_TRANSPARENT_GREEN_VALUE 0x3036
+#define EGL_TRANSPARENT_RED_VALUE 0x3037
+#define EGL_NONE 0x3038 /* Attrib list terminator */
+#define EGL_BIND_TO_TEXTURE_RGB 0x3039
+#define EGL_BIND_TO_TEXTURE_RGBA 0x303A
+#define EGL_MIN_SWAP_INTERVAL 0x303B
+#define EGL_MAX_SWAP_INTERVAL 0x303C
+#define EGL_LUMINANCE_SIZE 0x303D
+#define EGL_ALPHA_MASK_SIZE 0x303E
+#define EGL_COLOR_BUFFER_TYPE 0x303F
+#define EGL_RENDERABLE_TYPE 0x3040
+#define EGL_MATCH_NATIVE_PIXMAP 0x3041 /* Pseudo-attribute (not queryable) */
+#define EGL_CONFORMANT 0x3042
+
+/* Reserved 0x3041-0x304F for additional config attributes */
+
+/* Config attribute values */
+#define EGL_SLOW_CONFIG 0x3050 /* EGL_CONFIG_CAVEAT value */
+#define EGL_NON_CONFORMANT_CONFIG 0x3051 /* EGL_CONFIG_CAVEAT value */
+#define EGL_TRANSPARENT_RGB 0x3052 /* EGL_TRANSPARENT_TYPE value */
+#define EGL_RGB_BUFFER 0x308E /* EGL_COLOR_BUFFER_TYPE value */
+#define EGL_LUMINANCE_BUFFER 0x308F /* EGL_COLOR_BUFFER_TYPE value */
+
+/* More config attribute values, for EGL_TEXTURE_FORMAT */
+#define EGL_NO_TEXTURE 0x305C
+#define EGL_TEXTURE_RGB 0x305D
+#define EGL_TEXTURE_RGBA 0x305E
+#define EGL_TEXTURE_2D 0x305F
+
+/* Config attribute mask bits */
+#define EGL_PBUFFER_BIT 0x0001 /* EGL_SURFACE_TYPE mask bits */
+#define EGL_PIXMAP_BIT 0x0002 /* EGL_SURFACE_TYPE mask bits */
+#define EGL_WINDOW_BIT 0x0004 /* EGL_SURFACE_TYPE mask bits */
+#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020 /* EGL_SURFACE_TYPE mask bits */
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040 /* EGL_SURFACE_TYPE mask bits */
+#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200 /* EGL_SURFACE_TYPE mask bits */
+#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400 /* EGL_SURFACE_TYPE mask bits */
+
+#define EGL_OPENGL_ES_BIT 0x0001 /* EGL_RENDERABLE_TYPE mask bits */
+#define EGL_OPENVG_BIT 0x0002 /* EGL_RENDERABLE_TYPE mask bits */
+#define EGL_OPENGL_ES2_BIT 0x0004 /* EGL_RENDERABLE_TYPE mask bits */
+#define EGL_OPENGL_BIT 0x0008 /* EGL_RENDERABLE_TYPE mask bits */
+
+/* QueryString targets */
+#define EGL_VENDOR 0x3053
+#define EGL_VERSION 0x3054
+#define EGL_EXTENSIONS 0x3055
+#define EGL_CLIENT_APIS 0x308D
+
+/* QuerySurface / SurfaceAttrib / CreatePbufferSurface targets */
+#define EGL_HEIGHT 0x3056
+#define EGL_WIDTH 0x3057
+#define EGL_LARGEST_PBUFFER 0x3058
+#define EGL_TEXTURE_FORMAT 0x3080
+#define EGL_TEXTURE_TARGET 0x3081
+#define EGL_MIPMAP_TEXTURE 0x3082
+#define EGL_MIPMAP_LEVEL 0x3083
+#define EGL_RENDER_BUFFER 0x3086
+#define EGL_VG_COLORSPACE 0x3087
+#define EGL_VG_ALPHA_FORMAT 0x3088
+#define EGL_HORIZONTAL_RESOLUTION 0x3090
+#define EGL_VERTICAL_RESOLUTION 0x3091
+#define EGL_PIXEL_ASPECT_RATIO 0x3092
+#define EGL_SWAP_BEHAVIOR 0x3093
+#define EGL_MULTISAMPLE_RESOLVE 0x3099
+
+/* EGL_RENDER_BUFFER values / BindTexImage / ReleaseTexImage buffer targets */
+#define EGL_BACK_BUFFER 0x3084
+#define EGL_SINGLE_BUFFER 0x3085
+
+/* OpenVG color spaces */
+#define EGL_VG_COLORSPACE_sRGB 0x3089 /* EGL_VG_COLORSPACE value */
+#define EGL_VG_COLORSPACE_LINEAR 0x308A /* EGL_VG_COLORSPACE value */
+
+/* OpenVG alpha formats */
+#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B /* EGL_ALPHA_FORMAT value */
+#define EGL_VG_ALPHA_FORMAT_PRE 0x308C /* EGL_ALPHA_FORMAT value */
+
+/* Constant scale factor by which fractional display resolutions &
+ * aspect ratio are scaled when queried as integer values.
+ */
+#define EGL_DISPLAY_SCALING 10000
+
+/* Unknown display resolution/aspect ratio */
+#define EGL_UNKNOWN ((EGLint)-1)
+
+/* Back buffer swap behaviors */
+#define EGL_BUFFER_PRESERVED 0x3094 /* EGL_SWAP_BEHAVIOR value */
+#define EGL_BUFFER_DESTROYED 0x3095 /* EGL_SWAP_BEHAVIOR value */
+
+/* CreatePbufferFromClientBuffer buffer types */
+#define EGL_OPENVG_IMAGE 0x3096
+
+/* QueryContext targets */
+#define EGL_CONTEXT_CLIENT_TYPE 0x3097
+
+/* CreateContext attributes */
+#define EGL_CONTEXT_CLIENT_VERSION 0x3098
+
+/* Multisample resolution behaviors */
+#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A /* EGL_MULTISAMPLE_RESOLVE value */
+#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B /* EGL_MULTISAMPLE_RESOLVE value */
+
+/* BindAPI/QueryAPI targets */
+#define EGL_OPENGL_ES_API 0x30A0
+#define EGL_OPENVG_API 0x30A1
+#define EGL_OPENGL_API 0x30A2
+
+/* GetCurrentSurface targets */
+#define EGL_DRAW 0x3059
+#define EGL_READ 0x305A
+
+/* WaitNative engines */
+#define EGL_CORE_NATIVE_ENGINE 0x305B
+
+/* EGL 1.2 tokens renamed for consistency in EGL 1.3 */
+#define EGL_COLORSPACE EGL_VG_COLORSPACE
+#define EGL_ALPHA_FORMAT EGL_VG_ALPHA_FORMAT
+#define EGL_COLORSPACE_sRGB EGL_VG_COLORSPACE_sRGB
+#define EGL_COLORSPACE_LINEAR EGL_VG_COLORSPACE_LINEAR
+#define EGL_ALPHA_FORMAT_NONPRE EGL_VG_ALPHA_FORMAT_NONPRE
+#define EGL_ALPHA_FORMAT_PRE EGL_VG_ALPHA_FORMAT_PRE
+
+/* EGL extensions must request enum blocks from the Khronos
+ * API Registrar, who maintains the enumerant registry. Submit
+ * a bug in Khronos Bugzilla against task "Registry".
+ */
+
+
+
+/* EGL Functions */
+
+EGLAPI EGLint EGLAPIENTRY eglGetError(void);
+
+EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id);
+EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
+EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy);
+
+EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
+ EGLint config_size, EGLint *num_config);
+EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
+ EGLConfig *configs, EGLint config_size,
+ EGLint *num_config);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
+ EGLint attribute, EGLint *value);
+
+EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
+ EGLNativeWindowType win,
+ const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
+ const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
+ EGLNativePixmapType pixmap,
+ const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
+ EGLint attribute, EGLint *value);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api);
+EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void);
+
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(
+ EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
+ EGLConfig config, const EGLint *attrib_list);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
+ EGLint attribute, EGLint value);
+EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+
+
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval);
+
+
+EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config,
+ EGLContext share_context,
+ const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx);
+EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw,
+ EGLSurface read, EGLContext ctx);
+
+EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void);
+EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx,
+ EGLint attribute, EGLint *value);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine);
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface,
+ EGLNativePixmapType target);
+
+/* This is a generic function pointer type, whose name indicates it must
+ * be cast to the proper type *and calling convention* before use.
+ */
+typedef void (*__eglMustCastToProperFunctionPointerType)(void);
+
+/* Now, define eglGetProcAddress using the generic function ptr. type */
+EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY
+ eglGetProcAddress(const char *procname);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __egl_h_ */
diff --git a/Source/ThirdParty/ANGLE/include/EGL/eglext.h b/Source/ThirdParty/ANGLE/include/EGL/eglext.h
new file mode 100644
index 0000000..638e336
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/include/EGL/eglext.h
@@ -0,0 +1,222 @@
+#ifndef __eglext_h_
+#define __eglext_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2007-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+#include <EGL/eglplatform.h>
+
+/*************************************************************/
+
+/* Header file version number */
+/* Current version at http://www.khronos.org/registry/egl/ */
+/* $Revision: 10795 $ on $Date: 2010-03-19 17:04:17 -0700 (Fri, 19 Mar 2010) $ */
+#define EGL_EGLEXT_VERSION 5
+
+#ifndef EGL_KHR_config_attribs
+#define EGL_KHR_config_attribs 1
+#define EGL_CONFORMANT_KHR 0x3042 /* EGLConfig attribute */
+#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR 0x0020 /* EGL_SURFACE_TYPE bitfield */
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040 /* EGL_SURFACE_TYPE bitfield */
+#endif
+
+#ifndef EGL_KHR_lock_surface
+#define EGL_KHR_lock_surface 1
+#define EGL_READ_SURFACE_BIT_KHR 0x0001 /* EGL_LOCK_USAGE_HINT_KHR bitfield */
+#define EGL_WRITE_SURFACE_BIT_KHR 0x0002 /* EGL_LOCK_USAGE_HINT_KHR bitfield */
+#define EGL_LOCK_SURFACE_BIT_KHR 0x0080 /* EGL_SURFACE_TYPE bitfield */
+#define EGL_OPTIMAL_FORMAT_BIT_KHR 0x0100 /* EGL_SURFACE_TYPE bitfield */
+#define EGL_MATCH_FORMAT_KHR 0x3043 /* EGLConfig attribute */
+#define EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0 /* EGL_MATCH_FORMAT_KHR value */
+#define EGL_FORMAT_RGB_565_KHR 0x30C1 /* EGL_MATCH_FORMAT_KHR value */
+#define EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2 /* EGL_MATCH_FORMAT_KHR value */
+#define EGL_FORMAT_RGBA_8888_KHR 0x30C3 /* EGL_MATCH_FORMAT_KHR value */
+#define EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4 /* eglLockSurfaceKHR attribute */
+#define EGL_LOCK_USAGE_HINT_KHR 0x30C5 /* eglLockSurfaceKHR attribute */
+#define EGL_BITMAP_POINTER_KHR 0x30C6 /* eglQuerySurface attribute */
+#define EGL_BITMAP_PITCH_KHR 0x30C7 /* eglQuerySurface attribute */
+#define EGL_BITMAP_ORIGIN_KHR 0x30C8 /* eglQuerySurface attribute */
+#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR 0x30C9 /* eglQuerySurface attribute */
+#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA /* eglQuerySurface attribute */
+#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR 0x30CB /* eglQuerySurface attribute */
+#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC /* eglQuerySurface attribute */
+#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD /* eglQuerySurface attribute */
+#define EGL_LOWER_LEFT_KHR 0x30CE /* EGL_BITMAP_ORIGIN_KHR value */
+#define EGL_UPPER_LEFT_KHR 0x30CF /* EGL_BITMAP_ORIGIN_KHR value */
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay display, EGLSurface surface);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface);
+#endif
+
+#ifndef EGL_KHR_image
+#define EGL_KHR_image 1
+#define EGL_NATIVE_PIXMAP_KHR 0x30B0 /* eglCreateImageKHR target */
+typedef void *EGLImageKHR;
+#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0)
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
+#endif
+
+#ifndef EGL_KHR_vg_parent_image
+#define EGL_KHR_vg_parent_image 1
+#define EGL_VG_PARENT_IMAGE_KHR 0x30BA /* eglCreateImageKHR target */
+#endif
+
+#ifndef EGL_KHR_gl_texture_2D_image
+#define EGL_KHR_gl_texture_2D_image 1
+#define EGL_GL_TEXTURE_2D_KHR 0x30B1 /* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_LEVEL_KHR 0x30BC /* eglCreateImageKHR attribute */
+#endif
+
+#ifndef EGL_KHR_gl_texture_cubemap_image
+#define EGL_KHR_gl_texture_cubemap_image 1
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3 /* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4 /* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5 /* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6 /* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7 /* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8 /* eglCreateImageKHR target */
+#endif
+
+#ifndef EGL_KHR_gl_texture_3D_image
+#define EGL_KHR_gl_texture_3D_image 1
+#define EGL_GL_TEXTURE_3D_KHR 0x30B2 /* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD /* eglCreateImageKHR attribute */
+#endif
+
+#ifndef EGL_KHR_gl_renderbuffer_image
+#define EGL_KHR_gl_renderbuffer_image 1
+#define EGL_GL_RENDERBUFFER_KHR 0x30B9 /* eglCreateImageKHR target */
+#endif
+
+#ifndef EGL_KHR_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
+
+#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_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
+
+#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 unsigned long long 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
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/Source/ThirdParty/ANGLE/include/EGL/eglplatform.h b/Source/ThirdParty/ANGLE/include/EGL/eglplatform.h
new file mode 100644
index 0000000..22e855f
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/include/EGL/eglplatform.h
@@ -0,0 +1,110 @@
+#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: 9724 $ on $Date: 2009-12-02 02:05:33 -0800 (Wed, 02 Dec 2009) $
+ *
+ * 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".
+ */
+
+#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(__unix__)
+
+/* X11 (tentative) */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+typedef Display *EGLNativeDisplayType;
+typedef Pixmap EGLNativePixmapType;
+typedef Window EGLNativeWindowType;
+
+#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/Source/ThirdParty/ANGLE/include/GLES2/gl2.h b/Source/ThirdParty/ANGLE/include/GLES2/gl2.h
new file mode 100644
index 0000000..e1d3b87
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/include/GLES2/gl2.h
@@ -0,0 +1,621 @@
+#ifndef __gl2_h_
+#define __gl2_h_
+
+/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
+
+#include <GLES2/gl2platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/*-------------------------------------------------------------------------
+ * Data type definitions
+ *-----------------------------------------------------------------------*/
+
+typedef void GLvoid;
+typedef char GLchar;
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef khronos_int8_t GLbyte;
+typedef short GLshort;
+typedef int GLint;
+typedef int GLsizei;
+typedef khronos_uint8_t GLubyte;
+typedef unsigned short GLushort;
+typedef unsigned int GLuint;
+typedef khronos_float_t GLfloat;
+typedef khronos_float_t GLclampf;
+typedef khronos_int32_t GLfixed;
+
+/* GL types for handling large vertex buffer objects */
+typedef khronos_intptr_t GLintptr;
+typedef khronos_ssize_t GLsizeiptr;
+
+/* OpenGL ES core versions */
+#define GL_ES_VERSION_2_0 1
+
+/* ClearBufferMask */
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_COLOR_BUFFER_BIT 0x00004000
+
+/* Boolean */
+#define GL_FALSE 0
+#define GL_TRUE 1
+
+/* BeginMode */
+#define GL_POINTS 0x0000
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+
+/* AlphaFunction (not supported in ES20) */
+/* GL_NEVER */
+/* GL_LESS */
+/* GL_EQUAL */
+/* GL_LEQUAL */
+/* GL_GREATER */
+/* GL_NOTEQUAL */
+/* GL_GEQUAL */
+/* GL_ALWAYS */
+
+/* BlendingFactorDest */
+#define GL_ZERO 0
+#define GL_ONE 1
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+
+/* BlendingFactorSrc */
+/* GL_ZERO */
+/* GL_ONE */
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+/* GL_SRC_ALPHA */
+/* GL_ONE_MINUS_SRC_ALPHA */
+/* GL_DST_ALPHA */
+/* GL_ONE_MINUS_DST_ALPHA */
+
+/* BlendEquationSeparate */
+#define GL_FUNC_ADD 0x8006
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_RGB 0x8009 /* same as BLEND_EQUATION */
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+
+/* BlendSubtract */
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+
+/* Separate Blend Functions */
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_COLOR 0x8005
+
+/* Buffer Objects */
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STATIC_DRAW 0x88E4
+#define GL_DYNAMIC_DRAW 0x88E8
+
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+
+/* CullFaceMode */
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_FRONT_AND_BACK 0x0408
+
+/* DepthFunction */
+/* GL_NEVER */
+/* GL_LESS */
+/* GL_EQUAL */
+/* GL_LEQUAL */
+/* GL_GREATER */
+/* GL_NOTEQUAL */
+/* GL_GEQUAL */
+/* GL_ALWAYS */
+
+/* EnableCap */
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_CULL_FACE 0x0B44
+#define GL_BLEND 0x0BE2
+#define GL_DITHER 0x0BD0
+#define GL_STENCIL_TEST 0x0B90
+#define GL_DEPTH_TEST 0x0B71
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_COVERAGE 0x80A0
+
+/* ErrorCode */
+#define GL_NO_ERROR 0
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_OUT_OF_MEMORY 0x0505
+
+/* FrontFaceDirection */
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+
+/* GetPName */
+#define GL_LINE_WIDTH 0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_VIEWPORT 0x0BA2
+#define GL_SCISSOR_BOX 0x0C10
+/* GL_SCISSOR_TEST */
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_ALPHA_BITS 0x0D55
+#define GL_DEPTH_BITS 0x0D56
+#define GL_STENCIL_BITS 0x0D57
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+/* GL_POLYGON_OFFSET_FILL */
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+
+/* GetTextureParameter */
+/* GL_TEXTURE_MAG_FILTER */
+/* GL_TEXTURE_MIN_FILTER */
+/* GL_TEXTURE_WRAP_S */
+/* GL_TEXTURE_WRAP_T */
+
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+
+/* HintMode */
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+
+/* HintTarget */
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+
+/* DataType */
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_FIXED 0x140C
+
+/* PixelFormat */
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+
+/* PixelType */
+/* GL_UNSIGNED_BYTE */
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+
+/* Shaders */
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_DELETE_STATUS 0x8B80
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+
+/* StencilFunction */
+#define GL_NEVER 0x0200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+
+/* StencilOp */
+/* GL_ZERO */
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+#define GL_INVERT 0x150A
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+
+/* StringName */
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+
+/* TextureMagFilter */
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+
+/* TextureMinFilter */
+/* GL_NEAREST */
+/* GL_LINEAR */
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+
+/* TextureParameterName */
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+
+/* TextureTarget */
+/* GL_TEXTURE_2D */
+#define GL_TEXTURE 0x1702
+
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+
+/* TextureUnit */
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+
+/* TextureWrapMode */
+#define GL_REPEAT 0x2901
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_MIRRORED_REPEAT 0x8370
+
+/* Uniform Types */
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_CUBE 0x8B60
+
+/* Vertex Arrays */
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+
+/* Read Format */
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+
+/* Shader Source */
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_COMPILER 0x8DFA
+
+/* Shader Binary */
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+
+/* Shader Precision-Specified Types */
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+
+/* Framebuffer Object. */
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGB565 0x8D62
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_STENCIL_INDEX 0x1901
+#define GL_STENCIL_INDEX8 0x8D48
+
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+
+#define GL_NONE 0
+
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+
+/*-------------------------------------------------------------------------
+ * GL core functions.
+ *-----------------------------------------------------------------------*/
+
+GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name);
+GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void GL_APIENTRY glBlendEquation ( GLenum mode );
+GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void GL_APIENTRY glClearDepthf (GLclampf depth);
+GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
+GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
+GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
+GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
+GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
+GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
+GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glFinish (void);
+GL_APICALL void GL_APIENTRY glFlush (void);
+GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
+GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
+GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
+GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
+GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+GL_APICALL int GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name);
+GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
+GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL GLenum GL_APIENTRY glGetError (void);
+GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
+GL_APICALL int GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name);
+GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer);
+GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
+GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length);
+GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
+GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
+GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat x);
+GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint x);
+GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
+GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
+GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
+GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2_h_ */
diff --git a/Source/ThirdParty/ANGLE/include/GLES2/gl2ext.h b/Source/ThirdParty/ANGLE/include/GLES2/gl2ext.h
new file mode 100644
index 0000000..01844de
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/include/GLES2/gl2ext.h
@@ -0,0 +1,831 @@
+#ifndef __gl2ext_h_
+#define __gl2ext_h_
+
+/* $Revision: 10798 $ on $Date:: 2010-03-19 17:34:30 -0700 #$ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+#ifndef GL_APIENTRYP
+# define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+/*------------------------------------------------------------------------*
+ * OES extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_ETC1_RGB8_OES 0x8D64
+#endif
+
+/* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_PALETTE4_RGB8_OES 0x8B90
+#define GL_PALETTE4_RGBA8_OES 0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES 0x8B92
+#define GL_PALETTE4_RGBA4_OES 0x8B93
+#define GL_PALETTE4_RGB5_A1_OES 0x8B94
+#define GL_PALETTE8_RGB8_OES 0x8B95
+#define GL_PALETTE8_RGBA8_OES 0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES 0x8B97
+#define GL_PALETTE8_RGBA4_OES 0x8B98
+#define GL_PALETTE8_RGB5_A1_OES 0x8B99
+#endif
+
+/* GL_OES_depth24 */
+#ifndef GL_OES_depth24
+#define GL_DEPTH_COMPONENT24_OES 0x81A6
+#endif
+
+/* GL_OES_depth32 */
+#ifndef GL_OES_depth32
+#define GL_DEPTH_COMPONENT32_OES 0x81A7
+#endif
+
+/* GL_OES_depth_texture */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+typedef void* GLeglImageOES;
+#endif
+
+/* GL_OES_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
+
+/*------------------------------------------------------------------------*
+ * 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_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_multi_draw_arrays */
+/* No new tokens introduced by this extension. */
+
+/* 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_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_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368
+#endif
+
+/* GL_EXT_texture_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
+
+/*------------------------------------------------------------------------*
+ * 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
+
+/*------------------------------------------------------------------------*
+ * NV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+#endif
+
+/* 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
+
+/*------------------------------------------------------------------------*
+ * QCOM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* 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
+
+/*------------------------------------------------------------------------*
+ * 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 // alias GL_FRAMEBUFFER_BINDING
+#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
+
+/*------------------------------------------------------------------------*
+ * 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_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
+
+/*------------------------------------------------------------------------*
+ * EXT extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#endif
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_EXT_discard_framebuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+
+#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_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_EXT_read_format_bgra 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_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_EXT_texture_type_2_10_10_10_REV 1
+#endif
+
+/* GL_EXT_texture_compression_dxt1 */
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_EXT_texture_compression_dxt1 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
+
+/*------------------------------------------------------------------------*
+ * NV extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei, const GLuint *);
+GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei, GLuint *);
+GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint);
+GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint);
+GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint, GLenum, GLint *);
+GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint);
+GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint, GLenum);
+#endif
+typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (GL_APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#endif
+
+/* 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
+
+/*------------------------------------------------------------------------*
+ * QCOM extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_driver_control */
+#ifndef GL_QCOM_driver_control
+#define GL_QCOM_driver_control 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls);
+GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, 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
+
+/*------------------------------------------------------------------------*
+ * 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
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2ext_h_ */
diff --git a/Source/ThirdParty/ANGLE/include/GLES2/gl2platform.h b/Source/ThirdParty/ANGLE/include/GLES2/gl2platform.h
new file mode 100644
index 0000000..c9fa3c4
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/include/GLES2/gl2platform.h
@@ -0,0 +1,30 @@
+#ifndef __gl2platform_h_
+#define __gl2platform_h_
+
+/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* Platform-specific types and definitions for OpenGL ES 2.X gl2.h
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file. Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "OpenGL-ES" component "Registry".
+ */
+
+#include <KHR/khrplatform.h>
+
+#ifndef GL_APICALL
+#define GL_APICALL KHRONOS_APICALL
+#endif
+
+#ifndef GL_APIENTRY
+#define GL_APIENTRY KHRONOS_APIENTRY
+#endif
+
+#endif /* __gl2platform_h_ */
diff --git a/Source/ThirdParty/ANGLE/include/GLSLANG/ShaderLang.h b/Source/ThirdParty/ANGLE/include/GLSLANG/ShaderLang.h
new file mode 100644
index 0000000..e0a5cc8
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/include/GLSLANG/ShaderLang.h
@@ -0,0 +1,128 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef _COMPILER_INTERFACE_INCLUDED_
+#define _COMPILER_INTERFACE_INCLUDED_
+
+//
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler.
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+//
+// Driver must call this first, once, before doing any other
+// compiler operations.
+// If the function succeeds, the return value is nonzero, else zero.
+//
+int ShInitialize();
+//
+// Driver should call this at shutdown.
+// If the function succeeds, the return value is nonzero, else zero.
+//
+int ShFinalize();
+//
+// Types of languages the compiler can consume.
+//
+typedef enum {
+ EShLangVertex,
+ EShLangFragment,
+ EShLangCount,
+} EShLanguage;
+
+//
+// The language specification compiler conforms to.
+// It currently supports OpenGL ES and WebGL specifications.
+//
+typedef enum {
+ EShSpecGLES2,
+ EShSpecWebGL,
+} EShSpec;
+
+//
+// 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;
+} TBuiltInResource;
+
+//
+// Initialize built-in resources with minimum expected values.
+//
+void ShInitBuiltInResource(TBuiltInResource* resources);
+
+//
+// Optimization level for the compiler.
+//
+typedef enum {
+ EShOptNoGeneration,
+ EShOptNone,
+ EShOptSimple, // Optimizations that can be done quickly
+ EShOptFull, // Optimizations that will take more time
+} EShOptimizationLevel;
+
+enum TDebugOptions {
+ EDebugOpNone = 0x000,
+ EDebugOpIntermediate = 0x001, // Writes intermediate tree into info-log.
+};
+
+//
+// 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.
+//
+ShHandle ShConstructCompiler(EShLanguage, EShSpec, const TBuiltInResource*);
+void ShDestruct(ShHandle);
+
+//
+// The return value of ShCompile is boolean, indicating
+// success or failure.
+//
+// The info-log should be written by ShCompile into
+// ShHandle, so it can answer future queries.
+//
+int ShCompile(
+ const ShHandle,
+ const char* const shaderStrings[],
+ const int numStrings,
+ const EShOptimizationLevel,
+ int debugOptions
+ );
+
+//
+// All the following return 0 if the information is not
+// available in the object passed down, or the object is bad.
+//
+const char* ShGetInfoLog(const ShHandle);
+const char* ShGetObjectCode(const ShHandle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _COMPILER_INTERFACE_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/include/KHR/khrplatform.h b/Source/ThirdParty/ANGLE/include/KHR/khrplatform.h
new file mode 100644
index 0000000..8ec0d19
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/include/KHR/khrplatform.h
@@ -0,0 +1,269 @@
+#ifndef __khrplatform_h_
+#define __khrplatform_h_
+
+/*
+** Copyright (c) 2008-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Khronos platform-specific types and definitions.
+ *
+ * $Revision: 9356 $ on $Date: 2009-10-21 02:52:25 -0700 (Wed, 21 Oct 2009) $
+ *
+ * Adopters may modify this file to suit their platform. Adopters are
+ * encouraged to submit platform specific modifications to the Khronos
+ * group so that they can be included in future versions of this file.
+ * Please submit changes by sending them to the public Khronos Bugzilla
+ * (http://khronos.org/bugzilla) by filing a bug against product
+ * "Khronos (general)" component "Registry".
+ *
+ * A predefined template which fills in some of the bug fields can be
+ * reached using http://tinyurl.com/khrplatform-h-bugreport, but you
+ * must create a Bugzilla login first.
+ *
+ *
+ * See the Implementer's Guidelines for information about where this file
+ * should be located on your system and for more details of its use:
+ * http://www.khronos.org/registry/implementers_guide.pdf
+ *
+ * This file should be included as
+ * #include <KHR/khrplatform.h>
+ * by Khronos client API header files that use its types and defines.
+ *
+ * The types in khrplatform.h should only be used to define API-specific types.
+ *
+ * Types defined in khrplatform.h:
+ * khronos_int8_t signed 8 bit
+ * khronos_uint8_t unsigned 8 bit
+ * khronos_int16_t signed 16 bit
+ * khronos_uint16_t unsigned 16 bit
+ * khronos_int32_t signed 32 bit
+ * khronos_uint32_t unsigned 32 bit
+ * khronos_int64_t signed 64 bit
+ * khronos_uint64_t unsigned 64 bit
+ * khronos_intptr_t signed same number of bits as a pointer
+ * khronos_uintptr_t unsigned same number of bits as a pointer
+ * khronos_ssize_t signed size
+ * khronos_usize_t unsigned size
+ * khronos_float_t signed 32 bit floating point
+ * khronos_time_ns_t unsigned 64 bit time in nanoseconds
+ * khronos_utime_nanoseconds_t unsigned time interval or absolute time in
+ * nanoseconds
+ * khronos_stime_nanoseconds_t signed time interval in nanoseconds
+ * khronos_boolean_enum_t enumerated boolean type. This should
+ * only be used as a base type when a client API's boolean type is
+ * an enum. Client APIs which use an integer or other type for
+ * booleans cannot use this as the base type for their boolean.
+ *
+ * Tokens defined in khrplatform.h:
+ *
+ * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
+ *
+ * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
+ * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
+ *
+ * Calling convention macros defined in this file:
+ * KHRONOS_APICALL
+ * KHRONOS_APIENTRY
+ * KHRONOS_APIATTRIBUTES
+ *
+ * These may be used in function prototypes as:
+ *
+ * KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
+ * int arg1,
+ * int arg2) KHRONOS_APIATTRIBUTES;
+ */
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APICALL
+ *-------------------------------------------------------------------------
+ * This precedes the return type of the function in the function prototype.
+ */
+#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
+# define KHRONOS_APICALL __declspec(dllimport)
+#elif defined (__SYMBIAN32__)
+# define KHRONOS_APICALL IMPORT_C
+#else
+# define KHRONOS_APICALL
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIENTRY
+ *-------------------------------------------------------------------------
+ * This follows the return type of the function and precedes the function
+ * name in the function prototype.
+ */
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+ /* Win32 but not WinCE */
+# define KHRONOS_APIENTRY __stdcall
+#else
+# define KHRONOS_APIENTRY
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIATTRIBUTES
+ *-------------------------------------------------------------------------
+ * This follows the closing parenthesis of the function prototype arguments.
+ */
+#if defined (__ARMCC_2__)
+#define KHRONOS_APIATTRIBUTES __softfp
+#else
+#define KHRONOS_APIATTRIBUTES
+#endif
+
+/*-------------------------------------------------------------------------
+ * basic type definitions
+ *-----------------------------------------------------------------------*/
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
+
+
+/*
+ * Using <stdint.h>
+ */
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__VMS ) || defined(__sgi)
+
+/*
+ * Using <inttypes.h>
+ */
+#include <inttypes.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
+
+/*
+ * Win32
+ */
+typedef __int32 khronos_int32_t;
+typedef unsigned __int32 khronos_uint32_t;
+typedef __int64 khronos_int64_t;
+typedef unsigned __int64 khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__sun__) || defined(__digital__)
+
+/*
+ * Sun or Digital
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#if defined(__arch64__) || defined(_LP64)
+typedef long int khronos_int64_t;
+typedef unsigned long int khronos_uint64_t;
+#else
+typedef long long int khronos_int64_t;
+typedef unsigned long long int khronos_uint64_t;
+#endif /* __arch64__ */
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif 0
+
+/*
+ * Hypothetical platform with no float or int64 support
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#define KHRONOS_SUPPORT_INT64 0
+#define KHRONOS_SUPPORT_FLOAT 0
+
+#else
+
+/*
+ * Generic fallback
+ */
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#endif
+
+
+/*
+ * Types that are (so far) the same on all platforms
+ */
+typedef signed char khronos_int8_t;
+typedef unsigned char khronos_uint8_t;
+typedef signed short int khronos_int16_t;
+typedef unsigned short int khronos_uint16_t;
+typedef signed long int khronos_intptr_t;
+typedef unsigned long int khronos_uintptr_t;
+typedef signed long int khronos_ssize_t;
+typedef unsigned long int khronos_usize_t;
+
+#if KHRONOS_SUPPORT_FLOAT
+/*
+ * Float type
+ */
+typedef float khronos_float_t;
+#endif
+
+#if KHRONOS_SUPPORT_INT64
+/* Time types
+ *
+ * These types can be used to represent a time interval in nanoseconds or
+ * an absolute Unadjusted System Time. Unadjusted System Time is the number
+ * of nanoseconds since some arbitrary system event (e.g. since the last
+ * time the system booted). The Unadjusted System Time is an unsigned
+ * 64 bit value that wraps back to 0 every 584 years. Time intervals
+ * may be either signed or unsigned.
+ */
+typedef khronos_uint64_t khronos_utime_nanoseconds_t;
+typedef khronos_int64_t khronos_stime_nanoseconds_t;
+#endif
+
+/*
+ * Dummy value used to pad enum types to 32 bits.
+ */
+#ifndef KHRONOS_MAX_ENUM
+#define KHRONOS_MAX_ENUM 0x7FFFFFFF
+#endif
+
+/*
+ * Enumerated boolean type
+ *
+ * Values other than zero should be considered to be true. Therefore
+ * comparisons should not be made against KHRONOS_TRUE.
+ */
+typedef enum {
+ KHRONOS_FALSE = 0,
+ KHRONOS_TRUE = 1,
+ KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
+} khronos_boolean_enum_t;
+
+#endif /* __khrplatform_h_ */
diff --git a/Source/ThirdParty/ANGLE/src/build_angle.xcodeproj/project.pbxproj b/Source/ThirdParty/ANGLE/src/build_angle.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..f118435
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/build_angle.xcodeproj/project.pbxproj
@@ -0,0 +1,620 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXAggregateTarget section */
+ 1563D9916BFDAD853032CE1A /* All */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 77CEFB7B40F05B0A804E6B2B /* Build configuration list for PBXAggregateTarget "All" */;
+ buildPhases = (
+ );
+ dependencies = (
+ FB3C506411F792970081F5BA /* PBXTargetDependency */,
+ );
+ name = All;
+ productName = All;
+ };
+ 31349D665FAE642AEB49135E /* ANGLE Support */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 0AA54825BF5DF0A3FBA92B60 /* Build configuration list for PBXAggregateTarget "ANGLE Support" */;
+ buildPhases = (
+ FA0D7125DB06A7A7716A5910 /* Action "flex_glslang" */,
+ 0D513F8B923949C156DB02C5 /* Action "bison_glslang" */,
+ );
+ dependencies = (
+ );
+ name = "ANGLE Support";
+ productName = "translator_common Support";
+ };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+ 05563ADFEA15116D7233332F /* QualifierAlive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4857E18799D332C30EF460C7 /* QualifierAlive.cpp */; };
+ 0A216949103E1E228F9C12F0 /* InitializeDll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 60C3998C9CE66DE0C5B0FD99 /* InitializeDll.cpp */; };
+ 0D4064167398A6892809A09E /* glslang_tab.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A53D169CB849B861E15DF99A /* glslang_tab.cpp */; };
+ 3065D29E97FAC6E127388D15 /* Initialize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A54F2ED0D82D7BBCA4E9EEEA /* Initialize.cpp */; };
+ 32B1DBCD6B83F2146D787A62 /* atom.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C9B4616A65A5ABEF91FD6DC /* atom.c */; };
+ 35BE1BBEE6135A1CB0608EA8 /* cppstruct.c in Sources */ = {isa = PBXBuildFile; fileRef = 8058A0A2A0A02386867517EA /* cppstruct.c */; };
+ 3A96E9CAC8A25AF1564B652C /* memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 294F442A2606FEC55F12A28E /* memory.c */; };
+ 40FC189B8A246EDF14C2FDE3 /* intermOut.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEAF6F3126C2EC4397785C3F /* intermOut.cpp */; };
+ 50DF00005CC4212F6FB1291D /* Intermediate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F7C486C370A72938FE8160F /* Intermediate.cpp */; };
+ 6F9F875017A68ABE5D39FF19 /* ParseHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 976C831A75EBE009A9861796 /* ParseHelper.cpp */; };
+ 888F1382498E2D74AF2801C8 /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4ABA230FEA3654B030E4C4FB /* debug.cpp */; };
+ 9E8DFE1CCEF038BF2B65428C /* parseConst.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D2C9C8EB4A7EFF5B67FF9DBF /* parseConst.cpp */; };
+ ABA5C61B1B78B9A8D69F6AEC /* glslang.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB1F91D3D8CC446F35B00D1B /* glslang.cpp */; };
+ AC23F58FDD3C55F5CA18EED7 /* RemoveTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B436EFF06913FCB19C3522A7 /* RemoveTree.cpp */; };
+ AD85517F086FDCEF3947C403 /* symbols.c in Sources */ = {isa = PBXBuildFile; fileRef = F013A7240BDAE8A61413D8C0 /* symbols.c */; };
+ B4858417E54365BE8CDE3919 /* ossource_posix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE258486005F6696CC031622 /* ossource_posix.cpp */; };
+ B8BD2685A16B188CCDFB052B /* ShaderLang.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 56C7E99BA500A84C35216FE0 /* ShaderLang.cpp */; };
+ BEBBF4F0819EA3D03977A8FC /* InfoSink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6E6927BE5D3C2C82F86111DF /* InfoSink.cpp */; };
+ CB7F0EF0D6A89FA8C4DF5513 /* cpp.c in Sources */ = {isa = PBXBuildFile; fileRef = B75707B393B7EAB7DD9999CB /* cpp.c */; };
+ E1C7C5DFF0B2DFEC09387F4E /* PoolAlloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B64EABE738FC666A5E4E2F42 /* PoolAlloc.cpp */; };
+ E8C727AA8E9DC5E7B58857DF /* tokens.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D00745DA9914FDE274D03D5 /* tokens.c */; };
+ F098F463EDABCF0769007678 /* scanner.c in Sources */ = {isa = PBXBuildFile; fileRef = FF3AA694DF9A4455A813234D /* scanner.c */; };
+ F5AE2A292DFAF8C158412AA2 /* IntermTraverse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C4FE988EF9A293867E5C771B /* IntermTraverse.cpp */; };
+ F6ABD58F8CAB7641D8BFE935 /* SymbolTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B7E5B0F04635E6090F0DE8EF /* SymbolTable.cpp */; };
+ FB3C505711F7924A0081F5BA /* CodeGenGLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B7B1127C75B576FC00D74AED /* CodeGenGLSL.cpp */; };
+ FB3C505811F7924A0081F5BA /* OutputGLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 48B7402CC07A059FEF5EC351 /* OutputGLSL.cpp */; };
+ FB3C505911F7924A0081F5BA /* TranslatorGLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6FB70DC74A21FBCD665ABDF9 /* TranslatorGLSL.cpp */; };
+ FB3C508E11F7949E0081F5BA /* glslang.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB1F91D3D8CC446F35B00D1B /* glslang.cpp */; };
+ FB3C508F11F7949E0081F5BA /* glslang_tab.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A53D169CB849B861E15DF99A /* glslang_tab.cpp */; };
+ FB3C509211F794CE0081F5BA /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4ABA230FEA3654B030E4C4FB /* debug.cpp */; };
+ FB3C509311F794CE0081F5BA /* InfoSink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6E6927BE5D3C2C82F86111DF /* InfoSink.cpp */; };
+ FB3C509411F794CE0081F5BA /* Initialize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A54F2ED0D82D7BBCA4E9EEEA /* Initialize.cpp */; };
+ FB3C509511F794CE0081F5BA /* InitializeDll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 60C3998C9CE66DE0C5B0FD99 /* InitializeDll.cpp */; };
+ FB3C509611F794CE0081F5BA /* Intermediate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F7C486C370A72938FE8160F /* Intermediate.cpp */; };
+ FB3C509711F794CE0081F5BA /* intermOut.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEAF6F3126C2EC4397785C3F /* intermOut.cpp */; };
+ FB3C509811F794CE0081F5BA /* IntermTraverse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C4FE988EF9A293867E5C771B /* IntermTraverse.cpp */; };
+ FB3C509A11F794CE0081F5BA /* ossource_posix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE258486005F6696CC031622 /* ossource_posix.cpp */; };
+ FB3C509B11F794CE0081F5BA /* parseConst.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D2C9C8EB4A7EFF5B67FF9DBF /* parseConst.cpp */; };
+ FB3C509C11F794CE0081F5BA /* ParseHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 976C831A75EBE009A9861796 /* ParseHelper.cpp */; };
+ FB3C509D11F794CE0081F5BA /* PoolAlloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B64EABE738FC666A5E4E2F42 /* PoolAlloc.cpp */; };
+ FB3C509E11F794CE0081F5BA /* QualifierAlive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4857E18799D332C30EF460C7 /* QualifierAlive.cpp */; };
+ FB3C509F11F794CE0081F5BA /* RemoveTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B436EFF06913FCB19C3522A7 /* RemoveTree.cpp */; };
+ FB3C50A011F794CE0081F5BA /* ShaderLang.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 56C7E99BA500A84C35216FE0 /* ShaderLang.cpp */; };
+ FB3C50A111F794CE0081F5BA /* SymbolTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B7E5B0F04635E6090F0DE8EF /* SymbolTable.cpp */; };
+ FB3C50A411F794FF0081F5BA /* atom.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C9B4616A65A5ABEF91FD6DC /* atom.c */; };
+ FB3C50A511F794FF0081F5BA /* cpp.c in Sources */ = {isa = PBXBuildFile; fileRef = B75707B393B7EAB7DD9999CB /* cpp.c */; };
+ FB3C50A611F794FF0081F5BA /* cppstruct.c in Sources */ = {isa = PBXBuildFile; fileRef = 8058A0A2A0A02386867517EA /* cppstruct.c */; };
+ FB3C50A711F794FF0081F5BA /* memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 294F442A2606FEC55F12A28E /* memory.c */; };
+ FB3C50A811F794FF0081F5BA /* scanner.c in Sources */ = {isa = PBXBuildFile; fileRef = FF3AA694DF9A4455A813234D /* scanner.c */; };
+ FB3C50A911F794FF0081F5BA /* symbols.c in Sources */ = {isa = PBXBuildFile; fileRef = F013A7240BDAE8A61413D8C0 /* symbols.c */; };
+ FB3C50AA11F794FF0081F5BA /* tokens.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D00745DA9914FDE274D03D5 /* tokens.c */; };
+ FB3C50AB11F7951B0081F5BA /* TranslatorGLSL.h in Sources */ = {isa = PBXBuildFile; fileRef = DDD3B7E3B7B35A0B8469AB87 /* TranslatorGLSL.h */; };
+ FB3C50AC11F7951B0081F5BA /* OutputGLSL.h in Sources */ = {isa = PBXBuildFile; fileRef = 93D61CB0BCE54E069D71F920 /* OutputGLSL.h */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ E69BFBE2D1272620E46C3F8A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = DA188D8C6BF8073122539131 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 31349D665FAE642AEB49135E;
+ remoteInfo = "translator_common Support";
+ };
+ FB3C506311F792970081F5BA /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = DA188D8C6BF8073122539131 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = FB3C505511F7924A0081F5BA;
+ remoteInfo = angle;
+ };
+ FB3C50D011F79CCC0081F5BA /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = DA188D8C6BF8073122539131 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 31349D665FAE642AEB49135E;
+ remoteInfo = "ANGLE Support";
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 056FEADC7D95C6D4C9CF1113 /* scanner.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = scanner.h; sourceTree = "<group>"; };
+ 0C9B4616A65A5ABEF91FD6DC /* atom.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = atom.c; sourceTree = "<group>"; };
+ 12EAF028311EEA4753E82818 /* PoolAlloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PoolAlloc.h; sourceTree = "<group>"; };
+ 153BF06BF12C6F50496C6156 /* localintermediate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = localintermediate.h; sourceTree = "<group>"; };
+ 27E4C7ED0B82E18DCBEDF1C9 /* BaseTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseTypes.h; sourceTree = "<group>"; };
+ 294F442A2606FEC55F12A28E /* memory.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = memory.c; sourceTree = "<group>"; };
+ 2A765B86CBAF0D4A3E69DCA7 /* UnfoldSelect.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UnfoldSelect.h; sourceTree = "<group>"; };
+ 2D00745DA9914FDE274D03D5 /* tokens.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = tokens.c; sourceTree = "<group>"; };
+ 2E7C9B6E6DB751E12A2F6CB6 /* InitializeGlobals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InitializeGlobals.h; sourceTree = "<group>"; };
+ 3DDDC77216202A4DE1808BDB /* libtranslator_common.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libtranslator_common.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 3F7C486C370A72938FE8160F /* Intermediate.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Intermediate.cpp; sourceTree = "<group>"; };
+ 4857E18799D332C30EF460C7 /* QualifierAlive.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = QualifierAlive.cpp; sourceTree = "<group>"; };
+ 48B7402CC07A059FEF5EC351 /* OutputGLSL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = OutputGLSL.cpp; sourceTree = "<group>"; };
+ 4ABA230FEA3654B030E4C4FB /* debug.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = debug.cpp; sourceTree = "<group>"; };
+ 528FF201839C6F233E26FFDA /* cpp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cpp.h; sourceTree = "<group>"; };
+ 56C7E99BA500A84C35216FE0 /* ShaderLang.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ShaderLang.cpp; sourceTree = "<group>"; };
+ 580B2A31F7C51A59B40F11A3 /* compile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = compile.h; sourceTree = "<group>"; };
+ 5A21599C59BC1A75A7FABA34 /* OutputHLSL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OutputHLSL.h; sourceTree = "<group>"; };
+ 60C3998C9CE66DE0C5B0FD99 /* InitializeDll.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InitializeDll.cpp; sourceTree = "<group>"; };
+ 6BBC8224B9D8E234D117FA0C /* preprocess.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = preprocess.h; sourceTree = "<group>"; };
+ 6E6927BE5D3C2C82F86111DF /* InfoSink.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InfoSink.cpp; sourceTree = "<group>"; };
+ 6FB70DC74A21FBCD665ABDF9 /* TranslatorGLSL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TranslatorGLSL.cpp; sourceTree = "<group>"; };
+ 799DC9611EE2EA3BA7CF5477 /* intermediate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = intermediate.h; sourceTree = "<group>"; };
+ 7C6BB12AB099556CF379D78F /* SymbolTable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SymbolTable.h; sourceTree = "<group>"; };
+ 7D9CF376DC5799B4C6B3331E /* symbols.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = symbols.h; sourceTree = "<group>"; };
+ 8058A0A2A0A02386867517EA /* cppstruct.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = cppstruct.c; sourceTree = "<group>"; };
+ 831399DEE5DABA09570FB3E7 /* memory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = memory.h; sourceTree = "<group>"; };
+ 8513FAC699DB1558D1D49A48 /* Initialize.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Initialize.h; sourceTree = "<group>"; };
+ 85845FFF5A8E63364308236D /* InitializeParseContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InitializeParseContext.h; sourceTree = "<group>"; };
+ 89A6F7B1AD3918E64DF76EB1 /* slglobals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = slglobals.h; sourceTree = "<group>"; };
+ 8C3225C2F8C3573CD9725E66 /* glslang.y */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.yacc; path = glslang.y; sourceTree = "<group>"; };
+ 93D61CB0BCE54E069D71F920 /* OutputGLSL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OutputGLSL.h; sourceTree = "<group>"; };
+ 95276AA6B36FC1B1D913FCE4 /* debug.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = "<group>"; };
+ 976C831A75EBE009A9861796 /* ParseHelper.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ParseHelper.cpp; sourceTree = "<group>"; };
+ 9A5B5BB2526802479E19F993 /* OutputHLSL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = OutputHLSL.cpp; sourceTree = "<group>"; };
+ 9CED3AFF1E61B45EE1005656 /* atom.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = atom.h; sourceTree = "<group>"; };
+ 9D47B1AC82E4EE859AC54243 /* QualifierAlive.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QualifierAlive.h; sourceTree = "<group>"; };
+ A0CE43631849276A31187C7B /* InitializeDll.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InitializeDll.h; sourceTree = "<group>"; };
+ A3153D58F4BBBD98A84E4210 /* glslang.l */ = {isa = PBXFileReference; lastKnownFileType = text; path = glslang.l; sourceTree = "<group>"; };
+ A53D169CB849B861E15DF99A /* glslang_tab.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = glslang_tab.cpp; sourceTree = "<group>"; };
+ A54F2ED0D82D7BBCA4E9EEEA /* Initialize.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Initialize.cpp; sourceTree = "<group>"; };
+ AA53B6632C76F905DF08E564 /* Types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Types.h; sourceTree = "<group>"; };
+ AE65E139AE10DE9EFAD8D5B1 /* ShHandle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ShHandle.h; sourceTree = "<group>"; };
+ AE7674C52BDDDB28AF5FFD9F /* unistd.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = unistd.h; sourceTree = "<group>"; };
+ B2F5CA11EEA92DF2384EFD93 /* ConstantUnion.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ConstantUnion.h; sourceTree = "<group>"; };
+ B436EFF06913FCB19C3522A7 /* RemoveTree.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RemoveTree.cpp; sourceTree = "<group>"; };
+ B64EABE738FC666A5E4E2F42 /* PoolAlloc.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PoolAlloc.cpp; sourceTree = "<group>"; };
+ B75707B393B7EAB7DD9999CB /* cpp.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = cpp.c; sourceTree = "<group>"; };
+ B7B1127C75B576FC00D74AED /* CodeGenGLSL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CodeGenGLSL.cpp; sourceTree = "<group>"; };
+ B7E5B0F04635E6090F0DE8EF /* SymbolTable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolTable.cpp; sourceTree = "<group>"; };
+ BC66D6B47D9AF3286644BBE1 /* glslang_tab.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = glslang_tab.h; sourceTree = "<group>"; };
+ BE258486005F6696CC031622 /* ossource_posix.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ossource_posix.cpp; sourceTree = "<group>"; };
+ C3DAFF6BF12BB7F4784D6C7E /* TranslatorHLSL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TranslatorHLSL.cpp; sourceTree = "<group>"; };
+ C49549DCCAF450EB761520E1 /* CodeGenHLSL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CodeGenHLSL.cpp; sourceTree = "<group>"; };
+ C4FE988EF9A293867E5C771B /* IntermTraverse.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = IntermTraverse.cpp; sourceTree = "<group>"; };
+ C8BD59BD7056FFC21373C50A /* osinclude.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = osinclude.h; sourceTree = "<group>"; };
+ CB1F91D3D8CC446F35B00D1B /* glslang.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = glslang.cpp; sourceTree = "<group>"; };
+ CEE0C90DF6D504D1F3629711 /* ParseHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ParseHelper.h; sourceTree = "<group>"; };
+ CF2B62E0820C831AF812D000 /* build_angle.gyp */ = {isa = PBXFileReference; lastKnownFileType = text; path = build_angle.gyp; sourceTree = "<group>"; };
+ CFD12C6E46EBE0839BBE52B5 /* parser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = parser.h; sourceTree = "<group>"; };
+ D13C3693B9E40D37F2FAB34A /* tokens.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = tokens.h; sourceTree = "<group>"; };
+ D2C9C8EB4A7EFF5B67FF9DBF /* parseConst.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = parseConst.cpp; sourceTree = "<group>"; };
+ D40F78CB9BA0C89921FA319D /* RemoveTree.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoveTree.h; sourceTree = "<group>"; };
+ DDD3B7E3B7B35A0B8469AB87 /* TranslatorGLSL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TranslatorGLSL.h; sourceTree = "<group>"; };
+ DEAF6F3126C2EC4397785C3F /* intermOut.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = intermOut.cpp; sourceTree = "<group>"; };
+ DEEAFC618A3B33F1FBFE3536 /* MMap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MMap.h; sourceTree = "<group>"; };
+ E3711A48A0BF16B1CBD77AC9 /* UnfoldSelect.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = UnfoldSelect.cpp; sourceTree = "<group>"; };
+ E3A29B6E9C21B67C25FF0D2B /* TranslatorHLSL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TranslatorHLSL.h; sourceTree = "<group>"; };
+ F013A7240BDAE8A61413D8C0 /* symbols.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = symbols.c; sourceTree = "<group>"; };
+ F74618F18FE5448115017C44 /* Common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Common.h; sourceTree = "<group>"; };
+ F7B2971D4EB3836B94B7ECAF /* InfoSink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InfoSink.h; sourceTree = "<group>"; };
+ FB3C505D11F7924A0081F5BA /* libangle.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libangle.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ FF3AA694DF9A4455A813234D /* scanner.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = scanner.c; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ A5C994E74DB1E60338E7BC11 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FB3C505A11F7924A0081F5BA /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 0E8D65F584FDB84DAABD3969 /* preprocessor */ = {
+ isa = PBXGroup;
+ children = (
+ 0C9B4616A65A5ABEF91FD6DC /* atom.c */,
+ 9CED3AFF1E61B45EE1005656 /* atom.h */,
+ 580B2A31F7C51A59B40F11A3 /* compile.h */,
+ B75707B393B7EAB7DD9999CB /* cpp.c */,
+ 528FF201839C6F233E26FFDA /* cpp.h */,
+ 8058A0A2A0A02386867517EA /* cppstruct.c */,
+ 294F442A2606FEC55F12A28E /* memory.c */,
+ 831399DEE5DABA09570FB3E7 /* memory.h */,
+ CFD12C6E46EBE0839BBE52B5 /* parser.h */,
+ 6BBC8224B9D8E234D117FA0C /* preprocess.h */,
+ FF3AA694DF9A4455A813234D /* scanner.c */,
+ 056FEADC7D95C6D4C9CF1113 /* scanner.h */,
+ 89A6F7B1AD3918E64DF76EB1 /* slglobals.h */,
+ F013A7240BDAE8A61413D8C0 /* symbols.c */,
+ 7D9CF376DC5799B4C6B3331E /* symbols.h */,
+ 2D00745DA9914FDE274D03D5 /* tokens.c */,
+ D13C3693B9E40D37F2FAB34A /* tokens.h */,
+ );
+ path = preprocessor;
+ sourceTree = "<group>";
+ };
+ 196DB6AB006BB83503C7D786 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ 0E8D65F584FDB84DAABD3969 /* preprocessor */,
+ 27E4C7ED0B82E18DCBEDF1C9 /* BaseTypes.h */,
+ B7B1127C75B576FC00D74AED /* CodeGenGLSL.cpp */,
+ C49549DCCAF450EB761520E1 /* CodeGenHLSL.cpp */,
+ F74618F18FE5448115017C44 /* Common.h */,
+ B2F5CA11EEA92DF2384EFD93 /* ConstantUnion.h */,
+ 6E6927BE5D3C2C82F86111DF /* InfoSink.cpp */,
+ F7B2971D4EB3836B94B7ECAF /* InfoSink.h */,
+ A54F2ED0D82D7BBCA4E9EEEA /* Initialize.cpp */,
+ 8513FAC699DB1558D1D49A48 /* Initialize.h */,
+ 60C3998C9CE66DE0C5B0FD99 /* InitializeDll.cpp */,
+ A0CE43631849276A31187C7B /* InitializeDll.h */,
+ 2E7C9B6E6DB751E12A2F6CB6 /* InitializeGlobals.h */,
+ 85845FFF5A8E63364308236D /* InitializeParseContext.h */,
+ C4FE988EF9A293867E5C771B /* IntermTraverse.cpp */,
+ 3F7C486C370A72938FE8160F /* Intermediate.cpp */,
+ DEEAFC618A3B33F1FBFE3536 /* MMap.h */,
+ 48B7402CC07A059FEF5EC351 /* OutputGLSL.cpp */,
+ 93D61CB0BCE54E069D71F920 /* OutputGLSL.h */,
+ 9A5B5BB2526802479E19F993 /* OutputHLSL.cpp */,
+ 5A21599C59BC1A75A7FABA34 /* OutputHLSL.h */,
+ 976C831A75EBE009A9861796 /* ParseHelper.cpp */,
+ CEE0C90DF6D504D1F3629711 /* ParseHelper.h */,
+ B64EABE738FC666A5E4E2F42 /* PoolAlloc.cpp */,
+ 12EAF028311EEA4753E82818 /* PoolAlloc.h */,
+ 4857E18799D332C30EF460C7 /* QualifierAlive.cpp */,
+ 9D47B1AC82E4EE859AC54243 /* QualifierAlive.h */,
+ B436EFF06913FCB19C3522A7 /* RemoveTree.cpp */,
+ D40F78CB9BA0C89921FA319D /* RemoveTree.h */,
+ AE65E139AE10DE9EFAD8D5B1 /* ShHandle.h */,
+ 56C7E99BA500A84C35216FE0 /* ShaderLang.cpp */,
+ B7E5B0F04635E6090F0DE8EF /* SymbolTable.cpp */,
+ 7C6BB12AB099556CF379D78F /* SymbolTable.h */,
+ 6FB70DC74A21FBCD665ABDF9 /* TranslatorGLSL.cpp */,
+ DDD3B7E3B7B35A0B8469AB87 /* TranslatorGLSL.h */,
+ C3DAFF6BF12BB7F4784D6C7E /* TranslatorHLSL.cpp */,
+ E3A29B6E9C21B67C25FF0D2B /* TranslatorHLSL.h */,
+ AA53B6632C76F905DF08E564 /* Types.h */,
+ E3711A48A0BF16B1CBD77AC9 /* UnfoldSelect.cpp */,
+ 2A765B86CBAF0D4A3E69DCA7 /* UnfoldSelect.h */,
+ 4ABA230FEA3654B030E4C4FB /* debug.cpp */,
+ 95276AA6B36FC1B1D913FCE4 /* debug.h */,
+ A3153D58F4BBBD98A84E4210 /* glslang.l */,
+ 8C3225C2F8C3573CD9725E66 /* glslang.y */,
+ DEAF6F3126C2EC4397785C3F /* intermOut.cpp */,
+ 799DC9611EE2EA3BA7CF5477 /* intermediate.h */,
+ 153BF06BF12C6F50496C6156 /* localintermediate.h */,
+ C8BD59BD7056FFC21373C50A /* osinclude.h */,
+ BE258486005F6696CC031622 /* ossource_posix.cpp */,
+ D2C9C8EB4A7EFF5B67FF9DBF /* parseConst.cpp */,
+ AE7674C52BDDDB28AF5FFD9F /* unistd.h */,
+ );
+ name = Source;
+ path = compiler;
+ sourceTree = "<group>";
+ };
+ 466E1D0531A79B5813E8A7F8 /* Intermediates */ = {
+ isa = PBXGroup;
+ children = (
+ CB1F91D3D8CC446F35B00D1B /* glslang.cpp */,
+ A53D169CB849B861E15DF99A /* glslang_tab.cpp */,
+ BC66D6B47D9AF3286644BBE1 /* glslang_tab.h */,
+ );
+ name = Intermediates;
+ sourceTree = INTERMEDIATE_DIR;
+ };
+ 5BBEFF9B91738297B95C568D = {
+ isa = PBXGroup;
+ children = (
+ 196DB6AB006BB83503C7D786 /* Source */,
+ 466E1D0531A79B5813E8A7F8 /* Intermediates */,
+ E0EDC4130E7D374318CE72BE /* Products */,
+ B2C184C3543198BA51592EA4 /* Build */,
+ );
+ sourceTree = "<group>";
+ };
+ B2C184C3543198BA51592EA4 /* Build */ = {
+ isa = PBXGroup;
+ children = (
+ CF2B62E0820C831AF812D000 /* build_angle.gyp */,
+ );
+ name = Build;
+ sourceTree = "<group>";
+ };
+ E0EDC4130E7D374318CE72BE /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 3DDDC77216202A4DE1808BDB /* libtranslator_common.a */,
+ FB3C505D11F7924A0081F5BA /* libangle.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 6F4FD35CB3DFC89D70ECD432 /* translator_common */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 34BB38E3A74418B2A063B49E /* Build configuration list for PBXNativeTarget "translator_common" */;
+ buildPhases = (
+ EAA22CA63FD572FCCB913D22 /* Sources */,
+ A5C994E74DB1E60338E7BC11 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 291EE04202EC7967835FCC38 /* PBXTargetDependency */,
+ );
+ name = translator_common;
+ productName = translator_common;
+ productReference = 3DDDC77216202A4DE1808BDB /* libtranslator_common.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+ FB3C505511F7924A0081F5BA /* angle */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = FB3C505B11F7924A0081F5BA /* Build configuration list for PBXNativeTarget "angle" */;
+ buildPhases = (
+ FB3C505611F7924A0081F5BA /* Sources */,
+ FB3C505A11F7924A0081F5BA /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ FB3C50D111F79CCC0081F5BA /* PBXTargetDependency */,
+ );
+ name = angle;
+ productName = translator_glsl;
+ productReference = FB3C505D11F7924A0081F5BA /* libangle.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ DA188D8C6BF8073122539131 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ BuildIndependentTargetsInParallel = YES;
+ };
+ buildConfigurationList = 0E59F8FE4A8099E8DDCA4CE7 /* Build configuration list for PBXProject "build_angle" */;
+ compatibilityVersion = "Xcode 3.1";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
+ mainGroup = 5BBEFF9B91738297B95C568D;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 1563D9916BFDAD853032CE1A /* All */,
+ 6F4FD35CB3DFC89D70ECD432 /* translator_common */,
+ 31349D665FAE642AEB49135E /* ANGLE Support */,
+ FB3C505511F7924A0081F5BA /* angle */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 0D513F8B923949C156DB02C5 /* Action "bison_glslang" */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ compiler/glslang.y,
+ );
+ name = "Action \"bison_glslang\"";
+ outputPaths = (
+ "$(INTERMEDIATE_DIR)/glslang_tab.cpp",
+ "$(INTERMEDIATE_DIR)/glslang_tab.h",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "echo note: \"Executing bison on compiler/glslang.y\"\nexec bison --no-lines \"--defines=${INTERMEDIATE_DIR}/glslang_tab.h\" \"--skeleton=yacc.c\" \"--output=${INTERMEDIATE_DIR}/glslang_tab.cpp\" compiler/glslang.y\nexit 1\n";
+ showEnvVarsInLog = 0;
+ };
+ FA0D7125DB06A7A7716A5910 /* Action "flex_glslang" */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ compiler/glslang.l,
+ );
+ name = "Action \"flex_glslang\"";
+ outputPaths = (
+ "$(INTERMEDIATE_DIR)/glslang.cpp",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "echo note: \"Executing flex on compiler/glslang.l\"\nexec flex --noline --nounistd \"--outfile=${INTERMEDIATE_DIR}/glslang.cpp\" compiler/glslang.l\nexit 1\n";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ EAA22CA63FD572FCCB913D22 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 888F1382498E2D74AF2801C8 /* debug.cpp in Sources */,
+ BEBBF4F0819EA3D03977A8FC /* InfoSink.cpp in Sources */,
+ 3065D29E97FAC6E127388D15 /* Initialize.cpp in Sources */,
+ 0A216949103E1E228F9C12F0 /* InitializeDll.cpp in Sources */,
+ 50DF00005CC4212F6FB1291D /* Intermediate.cpp in Sources */,
+ 40FC189B8A246EDF14C2FDE3 /* intermOut.cpp in Sources */,
+ F5AE2A292DFAF8C158412AA2 /* IntermTraverse.cpp in Sources */,
+ 9E8DFE1CCEF038BF2B65428C /* parseConst.cpp in Sources */,
+ 6F9F875017A68ABE5D39FF19 /* ParseHelper.cpp in Sources */,
+ E1C7C5DFF0B2DFEC09387F4E /* PoolAlloc.cpp in Sources */,
+ 05563ADFEA15116D7233332F /* QualifierAlive.cpp in Sources */,
+ AC23F58FDD3C55F5CA18EED7 /* RemoveTree.cpp in Sources */,
+ B8BD2685A16B188CCDFB052B /* ShaderLang.cpp in Sources */,
+ F6ABD58F8CAB7641D8BFE935 /* SymbolTable.cpp in Sources */,
+ 32B1DBCD6B83F2146D787A62 /* atom.c in Sources */,
+ CB7F0EF0D6A89FA8C4DF5513 /* cpp.c in Sources */,
+ 35BE1BBEE6135A1CB0608EA8 /* cppstruct.c in Sources */,
+ 3A96E9CAC8A25AF1564B652C /* memory.c in Sources */,
+ F098F463EDABCF0769007678 /* scanner.c in Sources */,
+ AD85517F086FDCEF3947C403 /* symbols.c in Sources */,
+ E8C727AA8E9DC5E7B58857DF /* tokens.c in Sources */,
+ ABA5C61B1B78B9A8D69F6AEC /* glslang.cpp in Sources */,
+ 0D4064167398A6892809A09E /* glslang_tab.cpp in Sources */,
+ B4858417E54365BE8CDE3919 /* ossource_posix.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FB3C505611F7924A0081F5BA /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ FB3C50AB11F7951B0081F5BA /* TranslatorGLSL.h in Sources */,
+ FB3C50AC11F7951B0081F5BA /* OutputGLSL.h in Sources */,
+ FB3C50A411F794FF0081F5BA /* atom.c in Sources */,
+ FB3C50A511F794FF0081F5BA /* cpp.c in Sources */,
+ FB3C50A611F794FF0081F5BA /* cppstruct.c in Sources */,
+ FB3C50A711F794FF0081F5BA /* memory.c in Sources */,
+ FB3C50A811F794FF0081F5BA /* scanner.c in Sources */,
+ FB3C50A911F794FF0081F5BA /* symbols.c in Sources */,
+ FB3C50AA11F794FF0081F5BA /* tokens.c in Sources */,
+ FB3C508E11F7949E0081F5BA /* glslang.cpp in Sources */,
+ FB3C505711F7924A0081F5BA /* CodeGenGLSL.cpp in Sources */,
+ FB3C509211F794CE0081F5BA /* debug.cpp in Sources */,
+ FB3C509311F794CE0081F5BA /* InfoSink.cpp in Sources */,
+ FB3C509411F794CE0081F5BA /* Initialize.cpp in Sources */,
+ FB3C509511F794CE0081F5BA /* InitializeDll.cpp in Sources */,
+ FB3C509611F794CE0081F5BA /* Intermediate.cpp in Sources */,
+ FB3C509711F794CE0081F5BA /* intermOut.cpp in Sources */,
+ FB3C509811F794CE0081F5BA /* IntermTraverse.cpp in Sources */,
+ FB3C509A11F794CE0081F5BA /* ossource_posix.cpp in Sources */,
+ FB3C505811F7924A0081F5BA /* OutputGLSL.cpp in Sources */,
+ FB3C509B11F794CE0081F5BA /* parseConst.cpp in Sources */,
+ FB3C509C11F794CE0081F5BA /* ParseHelper.cpp in Sources */,
+ FB3C509D11F794CE0081F5BA /* PoolAlloc.cpp in Sources */,
+ FB3C509E11F794CE0081F5BA /* QualifierAlive.cpp in Sources */,
+ FB3C509F11F794CE0081F5BA /* RemoveTree.cpp in Sources */,
+ FB3C50A011F794CE0081F5BA /* ShaderLang.cpp in Sources */,
+ FB3C50A111F794CE0081F5BA /* SymbolTable.cpp in Sources */,
+ FB3C505911F7924A0081F5BA /* TranslatorGLSL.cpp in Sources */,
+ FB3C508F11F7949E0081F5BA /* glslang_tab.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 291EE04202EC7967835FCC38 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 31349D665FAE642AEB49135E /* ANGLE Support */;
+ targetProxy = E69BFBE2D1272620E46C3F8A /* PBXContainerItemProxy */;
+ };
+ FB3C506411F792970081F5BA /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = FB3C505511F7924A0081F5BA /* angle */;
+ targetProxy = FB3C506311F792970081F5BA /* PBXContainerItemProxy */;
+ };
+ FB3C50D111F79CCC0081F5BA /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 31349D665FAE642AEB49135E /* ANGLE Support */;
+ targetProxy = FB3C50D011F79CCC0081F5BA /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 00BF2EBCBDF5678F4BA2FA92 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "translator_common Support";
+ };
+ name = Default;
+ };
+ 1A12AA5D65ACDE71AE089EE3 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = All;
+ };
+ name = Default;
+ };
+ 1F3F1218B5135FBB067DE809 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ EXECUTABLE_PREFIX = lib;
+ HEADER_SEARCH_PATHS = (
+ .,
+ ../include,
+ );
+ PRODUCT_NAME = translator_common;
+ };
+ name = Default;
+ };
+ BC5793C9A1FF021A81C66559 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+ CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
+ INTERMEDIATE_DIR = "$(PROJECT_DERIVED_FILE_DIR)/$(CONFIGURATION)";
+ OBJROOT = "";
+ ONLY_ACTIVE_ARCH = YES;
+ SHARED_INTERMEDIATE_DIR = "$(SYMROOT)/DerivedSources/$(CONFIGURATION)";
+ SYMROOT = "$(BUILD_DIR)";
+ };
+ name = Default;
+ };
+ FB3C505C11F7924A0081F5BA /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ EXECUTABLE_PREFIX = lib;
+ HEADER_SEARCH_PATHS = (
+ .,
+ ../include,
+ );
+ PRODUCT_NAME = angle;
+ };
+ name = Default;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 0AA54825BF5DF0A3FBA92B60 /* Build configuration list for PBXAggregateTarget "ANGLE Support" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 00BF2EBCBDF5678F4BA2FA92 /* Default */,
+ );
+ defaultConfigurationIsVisible = 1;
+ defaultConfigurationName = Default;
+ };
+ 0E59F8FE4A8099E8DDCA4CE7 /* Build configuration list for PBXProject "build_angle" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ BC5793C9A1FF021A81C66559 /* Default */,
+ );
+ defaultConfigurationIsVisible = 1;
+ defaultConfigurationName = Default;
+ };
+ 34BB38E3A74418B2A063B49E /* Build configuration list for PBXNativeTarget "translator_common" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1F3F1218B5135FBB067DE809 /* Default */,
+ );
+ defaultConfigurationIsVisible = 1;
+ defaultConfigurationName = Default;
+ };
+ 77CEFB7B40F05B0A804E6B2B /* Build configuration list for PBXAggregateTarget "All" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1A12AA5D65ACDE71AE089EE3 /* Default */,
+ );
+ defaultConfigurationIsVisible = 1;
+ defaultConfigurationName = Default;
+ };
+ FB3C505B11F7924A0081F5BA /* Build configuration list for PBXNativeTarget "angle" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ FB3C505C11F7924A0081F5BA /* Default */,
+ );
+ defaultConfigurationIsVisible = 1;
+ defaultConfigurationName = Default;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = DA188D8C6BF8073122539131 /* Project object */;
+}
diff --git a/Source/ThirdParty/ANGLE/src/common/angleutils.h b/Source/ThirdParty/ANGLE/src/common/angleutils.h
new file mode 100644
index 0000000..24c766b
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/common/angleutils.h
@@ -0,0 +1,18 @@
+//
+// 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&)
+
+#endif // COMMON_ANGLEUTILS_H_
diff --git a/Source/ThirdParty/ANGLE/src/common/debug.cpp b/Source/ThirdParty/ANGLE/src/common/debug.cpp
new file mode 100644
index 0000000..d8d6ab8
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/common/debug.cpp
@@ -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.
+//
+
+// debug.cpp: Debugging utilities.
+
+#include "common/debug.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+static bool trace_on = true;
+
+namespace gl
+{
+void trace(const char *format, ...)
+{
+ if (trace_on)
+ {
+ if (format)
+ {
+ FILE *file = fopen("debug.txt", "a");
+
+ if (file)
+ {
+ va_list vararg;
+ va_start(vararg, format);
+ vfprintf(file, format, vararg);
+ va_end(vararg);
+
+ fclose(file);
+ }
+ }
+ }
+}
+}
diff --git a/Source/ThirdParty/ANGLE/src/common/debug.h b/Source/ThirdParty/ANGLE/src/common/debug.h
new file mode 100644
index 0000000..9a5135b
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/common/debug.h
@@ -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.
+//
+
+// debug.h: Debugging utilities.
+
+#ifndef COMMON_DEBUG_H_
+#define COMMON_DEBUG_H_
+
+#include <stdio.h>
+#include <assert.h>
+
+namespace gl
+{
+ // Outputs text to the debugging log
+ void trace(const char *format, ...);
+}
+
+// A macro to output a trace of a function call and its arguments to the debugging log
+#ifndef NDEBUG
+ #define TRACE(message, ...) gl::trace("trace: %s"message"\n", __FUNCTION__, __VA_ARGS__)
+#else
+ #define TRACE(...) ((void)0)
+#endif
+
+// A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing. Will occur even in release mode.
+#define FIXME(message, ...) gl::trace("fixme: %s"message"\n", __FUNCTION__, __VA_ARGS__)
+
+// A macro to output a function call and its arguments to the debugging log, in case of error. Will occur even in release mode.
+#define ERR(message, ...) gl::trace("err: %s"message"\n", __FUNCTION__, __VA_ARGS__)
+
+// A macro asserting a condition and outputting failures to the debug log
+#define ASSERT(expression) do { \
+ if(!(expression)) \
+ ERR("\t! Assert failed in %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \
+ assert(expression); \
+ } while(0)
+
+
+// A macro to indicate unimplemented functionality
+#ifndef NDEBUG
+ #define UNIMPLEMENTED() do { \
+ FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__); \
+ assert(false); \
+ } while(0)
+#else
+ #define UNIMPLEMENTED() FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__)
+#endif
+
+// A macro for code which is not expected to be reached under valid assumptions
+#ifndef NDEBUG
+ #define UNREACHABLE() do { \
+ ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \
+ assert(false); \
+ } while(0)
+#else
+ #define UNREACHABLE() ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__)
+#endif
+
+// A macro functioning as a compile-time assert to validate constant conditions
+#define META_ASSERT(condition) typedef int COMPILE_TIME_ASSERT_##__LINE__[static_cast<bool>(condition)?1:-1]
+
+#endif // COMMON_DEBUG_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/BaseTypes.h b/Source/ThirdParty/ANGLE/src/compiler/BaseTypes.h
new file mode 100644
index 0000000..9f4a860
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/BaseTypes.h
@@ -0,0 +1,147 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _BASICTYPES_INCLUDED_
+#define _BASICTYPES_INCLUDED_
+
+//
+// Precision qualifiers
+//
+enum TPrecision
+{
+ // These need to be kept sorted
+ EbpUndefined,
+ EbpLow,
+ EbpMedium,
+ EbpHigh,
+};
+
+inline const char* getPrecisionString(TPrecision p)
+{
+ switch(p)
+ {
+ case EbpHigh: return "highp"; break;
+ case EbpMedium: return "mediump"; break;
+ case EbpLow: return "lowp"; break;
+ default: return "mediump"; break; // Safest fallback
+ }
+}
+
+//
+// Basic type. Arrays, vectors, etc., are orthogonal to this.
+//
+enum TBasicType
+{
+ EbtVoid,
+ EbtFloat,
+ EbtInt,
+ EbtBool,
+ EbtGuardSamplerBegin, // non type: see implementation of IsSampler()
+ EbtSampler2D,
+ EbtSamplerCube,
+ EbtGuardSamplerEnd, // non type: see implementation of IsSampler()
+ EbtStruct,
+ EbtAddress, // should be deprecated??
+};
+
+inline const char* getBasicString(TBasicType t)
+{
+ switch (t)
+ {
+ case EbtVoid: return "void"; break;
+ case EbtFloat: return "float"; break;
+ case EbtInt: return "int"; break;
+ case EbtBool: return "bool"; break;
+ case EbtSampler2D: return "sampler2D"; break;
+ case EbtSamplerCube: return "samplerCube"; break;
+ case EbtStruct: return "structure"; break;
+ default: return "unknown type";
+ }
+}
+
+inline bool IsSampler(TBasicType type)
+{
+ return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd;
+}
+
+//
+// Qualifiers and built-ins. These are mainly used to see what can be read
+// or written, and by the machine dependent translator to know which registers
+// to allocate variables in. Since built-ins tend to go to different registers
+// than varying or uniform, it makes sense they are peers, not sub-classes.
+//
+enum TQualifier
+{
+ EvqTemporary, // For temporaries (within a function), read/write
+ EvqGlobal, // For globals read/write
+ EvqConst, // User defined constants and non-output parameters in functions
+ EvqAttribute, // Readonly
+ EvqVaryingIn, // readonly, fragment shaders only
+ EvqVaryingOut, // vertex shaders only read/write
+ EvqInvariantVaryingIn, // readonly, fragment shaders only
+ EvqInvariantVaryingOut, // vertex shaders only read/write
+ EvqUniform, // Readonly, vertex and fragment
+
+ // pack/unpack input and output
+ EvqInput,
+ EvqOutput,
+
+ // parameters
+ EvqIn,
+ EvqOut,
+ EvqInOut,
+ EvqConstReadOnly,
+
+ // built-ins written by vertex shader
+ EvqPosition,
+ EvqPointSize,
+
+ // built-ins read by fragment shader
+ EvqFragCoord,
+ EvqFrontFacing,
+ EvqPointCoord,
+
+ // built-ins written by fragment shader
+ EvqFragColor,
+ EvqFragData,
+
+ // end of list
+ EvqLast,
+};
+
+//
+// This is just for debug print out, carried along with the definitions above.
+//
+inline const char* getQualifierString(TQualifier q)
+{
+ switch(q)
+ {
+ case EvqTemporary: return "Temporary"; break;
+ case EvqGlobal: return "Global"; break;
+ case EvqConst: return "const"; break;
+ case EvqConstReadOnly: return "const"; break;
+ case EvqAttribute: return "attribute"; break;
+ case EvqVaryingIn: return "varying"; break;
+ case EvqVaryingOut: return "varying"; break;
+ case EvqInvariantVaryingIn: return "invariant varying"; break;
+ case EvqInvariantVaryingOut:return "invariant varying"; break;
+ case EvqUniform: return "uniform"; break;
+ case EvqIn: return "in"; break;
+ case EvqOut: return "out"; break;
+ case EvqInOut: return "inout"; break;
+ case EvqInput: return "input"; break;
+ case EvqOutput: return "output"; break;
+ case EvqPosition: return "Position"; break;
+ case EvqPointSize: return "PointSize"; break;
+ case EvqFragCoord: return "FragCoord"; break;
+ case EvqFrontFacing: return "FrontFacing"; break;
+ case EvqFragColor: return "FragColor"; break;
+ case EvqFragData: return "FragData"; break;
+ default: return "unknown qualifier";
+ }
+}
+
+#endif // _BASICTYPES_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/CodeGenGLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/CodeGenGLSL.cpp
new file mode 100644
index 0000000..855b092
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/CodeGenGLSL.cpp
@@ -0,0 +1,25 @@
+//
+// 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"
+
+//
+// This function must be provided to create the actual
+// compile object used by higher level code. It returns
+// a subclass of TCompiler.
+//
+TCompiler* ConstructCompiler(EShLanguage language, EShSpec spec)
+{
+ return new TranslatorGLSL(language, spec);
+}
+
+//
+// Delete the compiler made by ConstructCompiler
+//
+void DeleteCompiler(TCompiler* compiler)
+{
+ delete compiler;
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/CodeGenHLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/CodeGenHLSL.cpp
new file mode 100644
index 0000000..4db771d
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/CodeGenHLSL.cpp
@@ -0,0 +1,25 @@
+//
+// 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(EShLanguage language, EShSpec spec)
+{
+ return new TranslatorHLSL(language, spec);
+}
+
+//
+// Delete the compiler made by ConstructCompiler
+//
+void DeleteCompiler(TCompiler* compiler)
+{
+ delete compiler;
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/Common.h b/Source/ThirdParty/ANGLE/src/compiler/Common.h
new file mode 100644
index 0000000..65d0a51
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/Common.h
@@ -0,0 +1,76 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _COMMON_INCLUDED_
+#define _COMMON_INCLUDED_
+
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "compiler/PoolAlloc.h"
+
+typedef int TSourceLoc;
+const unsigned int SourceLocLineMask = 0xffff;
+const unsigned int SourceLocStringShift = 16;
+
+//
+// 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) {}
+};
+
+typedef TMap<TString, TString> TPragmaTable;
+
+#endif // _COMMON_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/ConstantUnion.h b/Source/ThirdParty/ANGLE/src/compiler/ConstantUnion.h
new file mode 100644
index 0000000..cf531ea
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/ConstantUnion.h
@@ -0,0 +1,288 @@
+//
+// 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:
+
+ POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+ void setIConst(int i) {iConst = i; type = EbtInt; }
+ void setFConst(float f) {fConst = f; type = EbtFloat; }
+ void setBConst(bool b) {bConst = b; type = EbtBool; }
+
+ int getIConst() { return iConst; }
+ float getFConst() { return fConst; }
+ bool getBConst() { return bConst; }
+ int getIConst() const { return iConst; }
+ float getFConst() const { return fConst; }
+ bool getBConst() const { return bConst; }
+
+ bool operator==(const int i) const
+ {
+ if (i == iConst)
+ return true;
+
+ return false;
+ }
+
+ bool operator==(const float f) const
+ {
+ if (f == fConst)
+ return true;
+
+ return false;
+ }
+
+ bool operator==(const bool b) const
+ {
+ if (b == bConst)
+ return true;
+
+ return false;
+ }
+
+ bool operator==(const ConstantUnion& constant) const
+ {
+ if (constant.type != type)
+ return false;
+
+ switch (type) {
+ case EbtInt:
+ if (constant.iConst == iConst)
+ return true;
+
+ break;
+ case EbtFloat:
+ if (constant.fConst == fConst)
+ return true;
+
+ break;
+ case EbtBool:
+ if (constant.bConst == bConst)
+ return true;
+
+ break;
+ }
+
+ return false;
+ }
+
+ bool operator!=(const int i) const
+ {
+ return !operator==(i);
+ }
+
+ bool operator!=(const float f) const
+ {
+ return !operator==(f);
+ }
+
+ bool operator!=(const bool b) const
+ {
+ return !operator==(b);
+ }
+
+ bool operator!=(const ConstantUnion& constant) const
+ {
+ return !operator==(constant);
+ }
+
+ bool operator>(const ConstantUnion& constant) const
+ {
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt:
+ if (iConst > constant.iConst)
+ return true;
+
+ return false;
+ case EbtFloat:
+ if (fConst > constant.fConst)
+ return true;
+
+ return false;
+ default:
+ assert(false && "Default missing");
+ return false;
+ }
+
+ return false;
+ }
+
+ bool operator<(const ConstantUnion& constant) const
+ {
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt:
+ if (iConst < constant.iConst)
+ return true;
+
+ return false;
+ case EbtFloat:
+ if (fConst < constant.fConst)
+ return true;
+
+ return false;
+ default:
+ assert(false && "Default missing");
+ return false;
+ }
+
+ return false;
+ }
+
+ ConstantUnion operator+(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst + constant.iConst); break;
+ case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator-(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst - constant.iConst); break;
+ case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator*(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst * constant.iConst); break;
+ case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator%(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator>>(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator<<(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator&(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst & constant.iConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator|(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst | constant.iConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator^(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator&&(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator||(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ TBasicType getType() const { return type; }
+private:
+
+ union {
+ int iConst; // used for ivec, scalar ints
+ bool bConst; // used for bvec, scalar bools
+ float fConst; // used for vec, mat, scalar floats
+ } ;
+
+ TBasicType type;
+};
+
+#endif // _CONSTANT_UNION_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/InfoSink.cpp b/Source/ThirdParty/ANGLE/src/compiler/InfoSink.cpp
new file mode 100644
index 0000000..317a88f
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/InfoSink.cpp
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/InfoSink.h"
+
+void TInfoSinkBase::prefix(TPrefixType message) {
+ switch(message) {
+ case EPrefixNone:
+ break;
+ case EPrefixWarning:
+ sink.append("WARNING: ");
+ break;
+ case EPrefixError:
+ sink.append("ERROR: ");
+ break;
+ case EPrefixInternalError:
+ sink.append("INTERNAL ERROR: ");
+ break;
+ case EPrefixUnimplemented:
+ sink.append("UNIMPLEMENTED: ");
+ break;
+ case EPrefixNote:
+ sink.append("NOTE: ");
+ break;
+ default:
+ sink.append("UNKOWN ERROR: ");
+ break;
+ }
+}
+
+void TInfoSinkBase::location(TSourceLoc loc) {
+ int string = loc >> SourceLocStringShift;
+ int line = loc & SourceLocLineMask;
+
+ 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/Source/ThirdParty/ANGLE/src/compiler/InfoSink.h b/Source/ThirdParty/ANGLE/src/compiler/InfoSink.h
new file mode 100644
index 0000000..4762778
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/InfoSink.h
@@ -0,0 +1,114 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#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(); }
+
+ 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/Source/ThirdParty/ANGLE/src/compiler/Initialize.cpp b/Source/ThirdParty/ANGLE/src/compiler/Initialize.cpp
new file mode 100644
index 0000000..6bfcf4f
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/Initialize.cpp
@@ -0,0 +1,617 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Create strings that declare built-in definitions, add built-ins that
+// cannot be expressed in the files, and establish mappings between
+// built-in functions and operators.
+//
+
+#include "compiler/Initialize.h"
+
+#include "compiler/intermediate.h"
+
+//============================================================================
+//
+// Prototypes for built-in functions seen by both vertex and fragment shaders.
+//
+//============================================================================
+static TString BuiltInFunctionsCommon()
+{
+ TString s;
+
+ //
+ // Angle and Trigonometric Functions.
+ //
+ s.append(TString("float radians(float degrees);"));
+ s.append(TString("vec2 radians(vec2 degrees);"));
+ s.append(TString("vec3 radians(vec3 degrees);"));
+ s.append(TString("vec4 radians(vec4 degrees);"));
+
+ s.append(TString("float degrees(float radians);"));
+ s.append(TString("vec2 degrees(vec2 radians);"));
+ s.append(TString("vec3 degrees(vec3 radians);"));
+ s.append(TString("vec4 degrees(vec4 radians);"));
+
+ s.append(TString("float sin(float angle);"));
+ s.append(TString("vec2 sin(vec2 angle);"));
+ s.append(TString("vec3 sin(vec3 angle);"));
+ s.append(TString("vec4 sin(vec4 angle);"));
+
+ s.append(TString("float cos(float angle);"));
+ s.append(TString("vec2 cos(vec2 angle);"));
+ s.append(TString("vec3 cos(vec3 angle);"));
+ s.append(TString("vec4 cos(vec4 angle);"));
+
+ s.append(TString("float tan(float angle);"));
+ s.append(TString("vec2 tan(vec2 angle);"));
+ s.append(TString("vec3 tan(vec3 angle);"));
+ s.append(TString("vec4 tan(vec4 angle);"));
+
+ s.append(TString("float asin(float x);"));
+ s.append(TString("vec2 asin(vec2 x);"));
+ s.append(TString("vec3 asin(vec3 x);"));
+ s.append(TString("vec4 asin(vec4 x);"));
+
+ s.append(TString("float acos(float x);"));
+ s.append(TString("vec2 acos(vec2 x);"));
+ s.append(TString("vec3 acos(vec3 x);"));
+ s.append(TString("vec4 acos(vec4 x);"));
+
+ s.append(TString("float atan(float y, float x);"));
+ s.append(TString("vec2 atan(vec2 y, vec2 x);"));
+ s.append(TString("vec3 atan(vec3 y, vec3 x);"));
+ s.append(TString("vec4 atan(vec4 y, vec4 x);"));
+
+ s.append(TString("float atan(float y_over_x);"));
+ s.append(TString("vec2 atan(vec2 y_over_x);"));
+ s.append(TString("vec3 atan(vec3 y_over_x);"));
+ s.append(TString("vec4 atan(vec4 y_over_x);"));
+
+ //
+ // Exponential Functions.
+ //
+ s.append(TString("float pow(float x, float y);"));
+ s.append(TString("vec2 pow(vec2 x, vec2 y);"));
+ s.append(TString("vec3 pow(vec3 x, vec3 y);"));
+ s.append(TString("vec4 pow(vec4 x, vec4 y);"));
+
+ s.append(TString("float exp(float x);"));
+ s.append(TString("vec2 exp(vec2 x);"));
+ s.append(TString("vec3 exp(vec3 x);"));
+ s.append(TString("vec4 exp(vec4 x);"));
+
+ s.append(TString("float log(float x);"));
+ s.append(TString("vec2 log(vec2 x);"));
+ s.append(TString("vec3 log(vec3 x);"));
+ s.append(TString("vec4 log(vec4 x);"));
+
+ s.append(TString("float exp2(float x);"));
+ s.append(TString("vec2 exp2(vec2 x);"));
+ s.append(TString("vec3 exp2(vec3 x);"));
+ s.append(TString("vec4 exp2(vec4 x);"));
+
+ s.append(TString("float log2(float x);"));
+ s.append(TString("vec2 log2(vec2 x);"));
+ s.append(TString("vec3 log2(vec3 x);"));
+ s.append(TString("vec4 log2(vec4 x);"));
+
+ s.append(TString("float sqrt(float x);"));
+ s.append(TString("vec2 sqrt(vec2 x);"));
+ s.append(TString("vec3 sqrt(vec3 x);"));
+ s.append(TString("vec4 sqrt(vec4 x);"));
+
+ s.append(TString("float inversesqrt(float x);"));
+ s.append(TString("vec2 inversesqrt(vec2 x);"));
+ s.append(TString("vec3 inversesqrt(vec3 x);"));
+ s.append(TString("vec4 inversesqrt(vec4 x);"));
+
+ //
+ // Common Functions.
+ //
+ s.append(TString("float abs(float x);"));
+ s.append(TString("vec2 abs(vec2 x);"));
+ s.append(TString("vec3 abs(vec3 x);"));
+ s.append(TString("vec4 abs(vec4 x);"));
+
+ s.append(TString("float sign(float x);"));
+ s.append(TString("vec2 sign(vec2 x);"));
+ s.append(TString("vec3 sign(vec3 x);"));
+ s.append(TString("vec4 sign(vec4 x);"));
+
+ s.append(TString("float floor(float x);"));
+ s.append(TString("vec2 floor(vec2 x);"));
+ s.append(TString("vec3 floor(vec3 x);"));
+ s.append(TString("vec4 floor(vec4 x);"));
+
+ s.append(TString("float ceil(float x);"));
+ s.append(TString("vec2 ceil(vec2 x);"));
+ s.append(TString("vec3 ceil(vec3 x);"));
+ s.append(TString("vec4 ceil(vec4 x);"));
+
+ s.append(TString("float fract(float x);"));
+ s.append(TString("vec2 fract(vec2 x);"));
+ s.append(TString("vec3 fract(vec3 x);"));
+ s.append(TString("vec4 fract(vec4 x);"));
+
+ s.append(TString("float mod(float x, float y);"));
+ s.append(TString("vec2 mod(vec2 x, float y);"));
+ s.append(TString("vec3 mod(vec3 x, float y);"));
+ s.append(TString("vec4 mod(vec4 x, float y);"));
+ s.append(TString("vec2 mod(vec2 x, vec2 y);"));
+ s.append(TString("vec3 mod(vec3 x, vec3 y);"));
+ s.append(TString("vec4 mod(vec4 x, vec4 y);"));
+
+ s.append(TString("float min(float x, float y);"));
+ s.append(TString("vec2 min(vec2 x, float y);"));
+ s.append(TString("vec3 min(vec3 x, float y);"));
+ s.append(TString("vec4 min(vec4 x, float y);"));
+ s.append(TString("vec2 min(vec2 x, vec2 y);"));
+ s.append(TString("vec3 min(vec3 x, vec3 y);"));
+ s.append(TString("vec4 min(vec4 x, vec4 y);"));
+
+ s.append(TString("float max(float x, float y);"));
+ s.append(TString("vec2 max(vec2 x, float y);"));
+ s.append(TString("vec3 max(vec3 x, float y);"));
+ s.append(TString("vec4 max(vec4 x, float y);"));
+ s.append(TString("vec2 max(vec2 x, vec2 y);"));
+ s.append(TString("vec3 max(vec3 x, vec3 y);"));
+ s.append(TString("vec4 max(vec4 x, vec4 y);"));
+
+ s.append(TString("float clamp(float x, float minVal, float maxVal);"));
+ s.append(TString("vec2 clamp(vec2 x, float minVal, float maxVal);"));
+ s.append(TString("vec3 clamp(vec3 x, float minVal, float maxVal);"));
+ s.append(TString("vec4 clamp(vec4 x, float minVal, float maxVal);"));
+ s.append(TString("vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal);"));
+ s.append(TString("vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal);"));
+ s.append(TString("vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal);"));
+
+ s.append(TString("float mix(float x, float y, float a);"));
+ s.append(TString("vec2 mix(vec2 x, vec2 y, float a);"));
+ s.append(TString("vec3 mix(vec3 x, vec3 y, float a);"));
+ s.append(TString("vec4 mix(vec4 x, vec4 y, float a);"));
+ s.append(TString("vec2 mix(vec2 x, vec2 y, vec2 a);"));
+ s.append(TString("vec3 mix(vec3 x, vec3 y, vec3 a);"));
+ s.append(TString("vec4 mix(vec4 x, vec4 y, vec4 a);"));
+
+ s.append(TString("float step(float edge, float x);"));
+ s.append(TString("vec2 step(vec2 edge, vec2 x);"));
+ s.append(TString("vec3 step(vec3 edge, vec3 x);"));
+ s.append(TString("vec4 step(vec4 edge, vec4 x);"));
+ s.append(TString("vec2 step(float edge, vec2 x);"));
+ s.append(TString("vec3 step(float edge, vec3 x);"));
+ s.append(TString("vec4 step(float edge, vec4 x);"));
+
+ s.append(TString("float smoothstep(float edge0, float edge1, float x);"));
+ s.append(TString("vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x);"));
+ s.append(TString("vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x);"));
+ s.append(TString("vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x);"));
+ s.append(TString("vec2 smoothstep(float edge0, float edge1, vec2 x);"));
+ s.append(TString("vec3 smoothstep(float edge0, float edge1, vec3 x);"));
+ s.append(TString("vec4 smoothstep(float edge0, float edge1, vec4 x);"));
+
+ //
+ // Geometric Functions.
+ //
+ s.append(TString("float length(float x);"));
+ s.append(TString("float length(vec2 x);"));
+ s.append(TString("float length(vec3 x);"));
+ s.append(TString("float length(vec4 x);"));
+
+ s.append(TString("float distance(float p0, float p1);"));
+ s.append(TString("float distance(vec2 p0, vec2 p1);"));
+ s.append(TString("float distance(vec3 p0, vec3 p1);"));
+ s.append(TString("float distance(vec4 p0, vec4 p1);"));
+
+ s.append(TString("float dot(float x, float y);"));
+ s.append(TString("float dot(vec2 x, vec2 y);"));
+ s.append(TString("float dot(vec3 x, vec3 y);"));
+ s.append(TString("float dot(vec4 x, vec4 y);"));
+
+ s.append(TString("vec3 cross(vec3 x, vec3 y);"));
+ s.append(TString("float normalize(float x);"));
+ s.append(TString("vec2 normalize(vec2 x);"));
+ s.append(TString("vec3 normalize(vec3 x);"));
+ s.append(TString("vec4 normalize(vec4 x);"));
+
+ s.append(TString("float faceforward(float N, float I, float Nref);"));
+ s.append(TString("vec2 faceforward(vec2 N, vec2 I, vec2 Nref);"));
+ s.append(TString("vec3 faceforward(vec3 N, vec3 I, vec3 Nref);"));
+ s.append(TString("vec4 faceforward(vec4 N, vec4 I, vec4 Nref);"));
+
+ s.append(TString("float reflect(float I, float N);"));
+ s.append(TString("vec2 reflect(vec2 I, vec2 N);"));
+ s.append(TString("vec3 reflect(vec3 I, vec3 N);"));
+ s.append(TString("vec4 reflect(vec4 I, vec4 N);"));
+
+ s.append(TString("float refract(float I, float N, float eta);"));
+ s.append(TString("vec2 refract(vec2 I, vec2 N, float eta);"));
+ s.append(TString("vec3 refract(vec3 I, vec3 N, float eta);"));
+ s.append(TString("vec4 refract(vec4 I, vec4 N, float eta);"));
+
+ //
+ // Matrix Functions.
+ //
+ s.append(TString("mat2 matrixCompMult(mat2 x, mat2 y);"));
+ s.append(TString("mat3 matrixCompMult(mat3 x, mat3 y);"));
+ s.append(TString("mat4 matrixCompMult(mat4 x, mat4 y);"));
+
+ //
+ // Vector relational functions.
+ //
+ s.append(TString("bvec2 lessThan(vec2 x, vec2 y);"));
+ s.append(TString("bvec3 lessThan(vec3 x, vec3 y);"));
+ s.append(TString("bvec4 lessThan(vec4 x, vec4 y);"));
+
+ s.append(TString("bvec2 lessThan(ivec2 x, ivec2 y);"));
+ s.append(TString("bvec3 lessThan(ivec3 x, ivec3 y);"));
+ s.append(TString("bvec4 lessThan(ivec4 x, ivec4 y);"));
+
+ s.append(TString("bvec2 lessThanEqual(vec2 x, vec2 y);"));
+ s.append(TString("bvec3 lessThanEqual(vec3 x, vec3 y);"));
+ s.append(TString("bvec4 lessThanEqual(vec4 x, vec4 y);"));
+
+ s.append(TString("bvec2 lessThanEqual(ivec2 x, ivec2 y);"));
+ s.append(TString("bvec3 lessThanEqual(ivec3 x, ivec3 y);"));
+ s.append(TString("bvec4 lessThanEqual(ivec4 x, ivec4 y);"));
+
+ s.append(TString("bvec2 greaterThan(vec2 x, vec2 y);"));
+ s.append(TString("bvec3 greaterThan(vec3 x, vec3 y);"));
+ s.append(TString("bvec4 greaterThan(vec4 x, vec4 y);"));
+
+ s.append(TString("bvec2 greaterThan(ivec2 x, ivec2 y);"));
+ s.append(TString("bvec3 greaterThan(ivec3 x, ivec3 y);"));
+ s.append(TString("bvec4 greaterThan(ivec4 x, ivec4 y);"));
+
+ s.append(TString("bvec2 greaterThanEqual(vec2 x, vec2 y);"));
+ s.append(TString("bvec3 greaterThanEqual(vec3 x, vec3 y);"));
+ s.append(TString("bvec4 greaterThanEqual(vec4 x, vec4 y);"));
+
+ s.append(TString("bvec2 greaterThanEqual(ivec2 x, ivec2 y);"));
+ s.append(TString("bvec3 greaterThanEqual(ivec3 x, ivec3 y);"));
+ s.append(TString("bvec4 greaterThanEqual(ivec4 x, ivec4 y);"));
+
+ s.append(TString("bvec2 equal(vec2 x, vec2 y);"));
+ s.append(TString("bvec3 equal(vec3 x, vec3 y);"));
+ s.append(TString("bvec4 equal(vec4 x, vec4 y);"));
+
+ s.append(TString("bvec2 equal(ivec2 x, ivec2 y);"));
+ s.append(TString("bvec3 equal(ivec3 x, ivec3 y);"));
+ s.append(TString("bvec4 equal(ivec4 x, ivec4 y);"));
+
+ s.append(TString("bvec2 equal(bvec2 x, bvec2 y);"));
+ s.append(TString("bvec3 equal(bvec3 x, bvec3 y);"));
+ s.append(TString("bvec4 equal(bvec4 x, bvec4 y);"));
+
+ s.append(TString("bvec2 notEqual(vec2 x, vec2 y);"));
+ s.append(TString("bvec3 notEqual(vec3 x, vec3 y);"));
+ s.append(TString("bvec4 notEqual(vec4 x, vec4 y);"));
+
+ s.append(TString("bvec2 notEqual(ivec2 x, ivec2 y);"));
+ s.append(TString("bvec3 notEqual(ivec3 x, ivec3 y);"));
+ s.append(TString("bvec4 notEqual(ivec4 x, ivec4 y);"));
+
+ s.append(TString("bvec2 notEqual(bvec2 x, bvec2 y);"));
+ s.append(TString("bvec3 notEqual(bvec3 x, bvec3 y);"));
+ s.append(TString("bvec4 notEqual(bvec4 x, bvec4 y);"));
+
+ s.append(TString("bool any(bvec2 x);"));
+ s.append(TString("bool any(bvec3 x);"));
+ s.append(TString("bool any(bvec4 x);"));
+
+ s.append(TString("bool all(bvec2 x);"));
+ s.append(TString("bool all(bvec3 x);"));
+ s.append(TString("bool all(bvec4 x);"));
+
+ s.append(TString("bvec2 not(bvec2 x);"));
+ s.append(TString("bvec3 not(bvec3 x);"));
+ s.append(TString("bvec4 not(bvec4 x);"));
+
+ //
+ // Texture Functions.
+ //
+ s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord);"));
+ s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord);"));
+ s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord);"));
+
+ s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord);"));
+
+ //
+ // Noise functions.
+ //
+ //s.append(TString("float noise1(float x);"));
+ //s.append(TString("float noise1(vec2 x);"));
+ //s.append(TString("float noise1(vec3 x);"));
+ //s.append(TString("float noise1(vec4 x);"));
+
+ //s.append(TString("vec2 noise2(float x);"));
+ //s.append(TString("vec2 noise2(vec2 x);"));
+ //s.append(TString("vec2 noise2(vec3 x);"));
+ //s.append(TString("vec2 noise2(vec4 x);"));
+
+ //s.append(TString("vec3 noise3(float x);"));
+ //s.append(TString("vec3 noise3(vec2 x);"));
+ //s.append(TString("vec3 noise3(vec3 x);"));
+ //s.append(TString("vec3 noise3(vec4 x);"));
+
+ //s.append(TString("vec4 noise4(float x);"));
+ //s.append(TString("vec4 noise4(vec2 x);"));
+ //s.append(TString("vec4 noise4(vec3 x);"));
+ //s.append(TString("vec4 noise4(vec4 x);"));
+
+ s.append(TString("\n"));
+ return s;
+}
+
+//============================================================================
+//
+// Prototypes for built-in functions seen by vertex shaders only.
+//
+//============================================================================
+static TString BuiltInFunctionsVertex()
+{
+ 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);"));
+
+ s.append(TString("\n"));
+ return s;
+}
+
+//============================================================================
+//
+// Prototypes for built-in functions seen by fragment shaders only.
+//
+//============================================================================
+static TString BuiltInFunctionsFragment()
+{
+ 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);"));
+
+ //s.append(TString("float dFdx(float p);"));
+ //s.append(TString("vec2 dFdx(vec2 p);"));
+ //s.append(TString("vec3 dFdx(vec3 p);"));
+ //s.append(TString("vec4 dFdx(vec4 p);"));
+
+ //s.append(TString("float dFdy(float p);"));
+ //s.append(TString("vec2 dFdy(vec2 p);"));
+ //s.append(TString("vec3 dFdy(vec3 p);"));
+ //s.append(TString("vec4 dFdy(vec4 p);"));
+
+ s.append(TString("float fwidth(float p);"));
+ s.append(TString("vec2 fwidth(vec2 p);"));
+ s.append(TString("vec3 fwidth(vec3 p);"));
+ s.append(TString("vec4 fwidth(vec4 p);"));
+
+ s.append(TString("\n"));
+ 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;"));
+
+ s.append(TString("\n"));
+ return s;
+}
+
+//============================================================================
+//
+// Default precision for vertex shaders.
+//
+//============================================================================
+static TString DefaultPrecisionVertex()
+{
+ TString s;
+
+ s.append(TString("precision highp int;"));
+ s.append(TString("precision highp float;"));
+
+ s.append(TString("\n"));
+ 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
+
+ s.append(TString("\n"));
+ return s;
+}
+
+//============================================================================
+//
+// Implementation dependent built-in constants.
+//
+//============================================================================
+static TString BuiltInConstants(const TBuiltInResource &resources)
+{
+ TStringStream s;
+
+ s << "const int gl_MaxVertexAttribs = " << resources.MaxVertexAttribs << ";";
+ s << "const int gl_MaxVertexUniformVectors = " << resources.MaxVertexUniformVectors << ";";
+
+ s << "const int gl_MaxVaryingVectors = " << resources.MaxVaryingVectors << ";";
+ s << "const int gl_MaxVertexTextureImageUnits = " << resources.MaxVertexTextureImageUnits << ";";
+ s << "const int gl_MaxCombinedTextureImageUnits = " << resources.MaxCombinedTextureImageUnits << ";";
+ s << "const int gl_MaxTextureImageUnits = " << resources.MaxTextureImageUnits << ";";
+ s << "const int gl_MaxFragmentUniformVectors = " << resources.MaxFragmentUniformVectors << ";";
+ s << "const int gl_MaxDrawBuffers = " << resources.MaxDrawBuffers << ";";
+
+ return s.str();
+}
+
+void TBuiltIns::initialize(EShLanguage language, EShSpec spec, const TBuiltInResource& resources)
+{
+ switch (language) {
+ case EShLangFragment:
+ builtInStrings.push_back(DefaultPrecisionFragment());
+ builtInStrings.push_back(BuiltInFunctionsCommon());
+ builtInStrings.push_back(BuiltInFunctionsFragment());
+ builtInStrings.push_back(StandardUniforms());
+ break;
+
+ case EShLangVertex:
+ builtInStrings.push_back(DefaultPrecisionVertex());
+ builtInStrings.push_back(BuiltInFunctionsCommon());
+ builtInStrings.push_back(BuiltInFunctionsVertex());
+ builtInStrings.push_back(StandardUniforms());
+ break;
+
+ default: assert(false && "Language not supported");
+ }
+
+ builtInStrings.push_back(BuiltInConstants(resources));
+}
+
+void IdentifyBuiltIns(EShLanguage language, EShSpec spec, const TBuiltInResource& resources, TSymbolTable& symbolTable)
+{
+ //
+ // First, insert some special built-in variables that are not in
+ // the built-in header files.
+ //
+ switch(language) {
+ case EShLangFragment:
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2)));
+ break;
+
+ case EShLangVertex:
+ 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(language) {
+ case EShLangVertex:
+ break;
+ case EShLangFragment:
+ //symbolTable.relateToOperator("dFdx", EOpDPdx); // OES_standard_derivatives extension
+ //symbolTable.relateToOperator("dFdy", EOpDPdy); // OES_standard_derivatives extension
+ //symbolTable.relateToOperator("fwidth", EOpFwidth); // OES_standard_derivatives extension
+ break;
+ default: break;
+ }
+
+ // Finally add resource-specific variables.
+ switch(language) {
+ case EShLangFragment: {
+ // Set up gl_FragData. The array size.
+ TType fragData(EbtFloat, EbpMedium, EvqFragColor, 4, false, true);
+ fragData.setArraySize(resources.MaxDrawBuffers);
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData));
+ }
+ break;
+ default: break;
+ }
+}
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/Initialize.h b/Source/ThirdParty/ANGLE/src/compiler/Initialize.h
new file mode 100644
index 0000000..c078659
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/Initialize.h
@@ -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.
+//
+
+#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(EShLanguage language, EShSpec spec, const TBuiltInResource& resources);
+ const TBuiltInStrings& getBuiltInStrings() { return builtInStrings; }
+
+protected:
+ TBuiltInStrings builtInStrings;
+};
+
+void IdentifyBuiltIns(EShLanguage language, EShSpec spec, const TBuiltInResource& resources,
+ TSymbolTable& symbolTable);
+
+extern "C" int InitPreprocessor(void);
+extern "C" int FinalizePreprocessor(void);
+
+#endif // _INITIALIZE_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/InitializeDll.cpp b/Source/ThirdParty/ANGLE/src/compiler/InitializeDll.cpp
new file mode 100644
index 0000000..8763cfe
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/InitializeDll.cpp
@@ -0,0 +1,115 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/InitializeDll.h"
+
+#include "compiler/InitializeGlobals.h"
+#include "compiler/InitializeParseContext.h"
+#include "compiler/osinclude.h"
+
+OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
+
+bool InitProcess()
+{
+ if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) {
+ //
+ // Function is re-entrant.
+ //
+ return true;
+ }
+
+ ThreadInitializeIndex = OS_AllocTLSIndex();
+
+ if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "InitProcess(): Failed to allocate TLS area for init flag");
+ return false;
+ }
+
+
+ if (!InitializePoolIndex()) {
+ assert(0 && "InitProcess(): Failed to initalize global pool");
+ return false;
+ }
+
+ if (!InitializeParseContextIndex()) {
+ assert(0 && "InitProcess(): Failed to initalize parse context");
+ return false;
+ }
+
+ return InitThread();
+}
+
+bool DetachProcess()
+{
+ bool success = true;
+
+ if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
+ return true;
+
+ success = DetachThread();
+
+ if (!FreeParseContextIndex())
+ success = false;
+
+ FreePoolIndex();
+
+ OS_FreeTLSIndex(ThreadInitializeIndex);
+ ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
+
+ return success;
+}
+
+bool InitThread()
+{
+ //
+ // This function is re-entrant
+ //
+ if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "InitThread(): Process hasn't been initalised.");
+ return false;
+ }
+
+ if (OS_GetTLSValue(ThreadInitializeIndex) != 0)
+ return true;
+
+ InitializeGlobalPools();
+
+ if (!InitializeGlobalParseContext())
+ return false;
+
+ if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) {
+ assert(0 && "InitThread(): Unable to set init flag.");
+ return false;
+ }
+
+ return true;
+}
+
+bool DetachThread()
+{
+ bool success = true;
+
+ if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
+ return true;
+
+ //
+ // Function is re-entrant and this thread may not have been initalised.
+ //
+ if (OS_GetTLSValue(ThreadInitializeIndex) != 0) {
+ if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) {
+ assert(0 && "DetachThread(): Unable to clear init flag.");
+ success = false;
+ }
+
+ if (!FreeParseContext())
+ success = false;
+
+ FreeGlobalPools();
+ }
+
+ return success;
+}
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/InitializeDll.h b/Source/ThirdParty/ANGLE/src/compiler/InitializeDll.h
new file mode 100644
index 0000000..857238e
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/InitializeDll.h
@@ -0,0 +1,16 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef __INITIALIZEDLL_H
+#define __INITIALIZEDLL_H
+
+bool InitProcess();
+bool DetachProcess();
+
+bool InitThread();
+bool DetachThread();
+
+#endif // __INITIALIZEDLL_H
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/InitializeGlobals.h b/Source/ThirdParty/ANGLE/src/compiler/InitializeGlobals.h
new file mode 100644
index 0000000..842a452
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/InitializeGlobals.h
@@ -0,0 +1,15 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef __INITIALIZE_GLOBALS_INCLUDED_
+#define __INITIALIZE_GLOBALS_INCLUDED_
+
+void InitializeGlobalPools();
+void FreeGlobalPools();
+bool InitializePoolIndex();
+void FreePoolIndex();
+
+#endif // __INITIALIZE_GLOBALS_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/InitializeParseContext.h b/Source/ThirdParty/ANGLE/src/compiler/InitializeParseContext.h
new file mode 100644
index 0000000..760fd09
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/InitializeParseContext.h
@@ -0,0 +1,16 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef __INITIALIZE_PARSE_CONTEXT_INCLUDED_
+#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_
+
+bool InitializeParseContextIndex();
+bool FreeParseContextIndex();
+
+bool InitializeGlobalParseContext();
+bool FreeParseContext();
+
+#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/IntermTraverse.cpp b/Source/ThirdParty/ANGLE/src/compiler/IntermTraverse.cpp
new file mode 100644
index 0000000..34a6f3c
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/IntermTraverse.cpp
@@ -0,0 +1,293 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/intermediate.h"
+
+//
+// Traverse the intermediate representation tree, and
+// call a node type specific function for each node.
+// Done recursively through the member function Traverse().
+// Node types can be skipped if their function to call is 0,
+// but their subtree will still be traversed.
+// Nodes with children can have their whole subtree skipped
+// if preVisit is turned on and the type specific function
+// returns false.
+//
+// preVisit, postVisit, and rightToLeft control what order
+// nodes are visited in.
+//
+
+//
+// Traversal functions for terminals are straighforward....
+//
+void TIntermSymbol::traverse(TIntermTraverser* it)
+{
+ it->visitSymbol(this);
+}
+
+void TIntermConstantUnion::traverse(TIntermTraverser* it)
+{
+ it->visitConstantUnion(this);
+}
+
+//
+// Traverse a binary node.
+//
+void TIntermBinary::traverse(TIntermTraverser* it)
+{
+ bool visit = true;
+
+ //
+ // visit the node before children if pre-visiting.
+ //
+ if(it->preVisit)
+ {
+ visit = it->visitBinary(PreVisit, this);
+ }
+
+ //
+ // Visit the children, in the right order.
+ //
+ if(visit)
+ {
+ it->incrementDepth();
+
+ if(it->rightToLeft)
+ {
+ if(right)
+ {
+ right->traverse(it);
+ }
+
+ if(it->inVisit)
+ {
+ visit = it->visitBinary(InVisit, this);
+ }
+
+ if(visit && left)
+ {
+ left->traverse(it);
+ }
+ }
+ else
+ {
+ if(left)
+ {
+ left->traverse(it);
+ }
+
+ if(it->inVisit)
+ {
+ visit = it->visitBinary(InVisit, this);
+ }
+
+ if(visit && right)
+ {
+ right->traverse(it);
+ }
+ }
+
+ it->decrementDepth();
+ }
+
+ //
+ // Visit the node after the children, if requested and the traversal
+ // hasn't been cancelled yet.
+ //
+ if(visit && it->postVisit)
+ {
+ it->visitBinary(PostVisit, this);
+ }
+}
+
+//
+// Traverse a unary node. Same comments in binary node apply here.
+//
+void TIntermUnary::traverse(TIntermTraverser* it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitUnary(PreVisit, this);
+
+ if (visit) {
+ it->incrementDepth();
+ operand->traverse(it);
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitUnary(PostVisit, this);
+}
+
+//
+// Traverse an aggregate node. Same comments in binary node apply here.
+//
+void TIntermAggregate::traverse(TIntermTraverser* it)
+{
+ bool visit = true;
+
+ if(it->preVisit)
+ {
+ visit = it->visitAggregate(PreVisit, this);
+ }
+
+ if(visit)
+ {
+ it->incrementDepth();
+
+ if(it->rightToLeft)
+ {
+ for(TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++)
+ {
+ (*sit)->traverse(it);
+
+ if(visit && it->inVisit)
+ {
+ if(*sit != sequence.front())
+ {
+ visit = it->visitAggregate(InVisit, this);
+ }
+ }
+ }
+ }
+ else
+ {
+ for(TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
+ {
+ (*sit)->traverse(it);
+
+ if(visit && it->inVisit)
+ {
+ if(*sit != sequence.back())
+ {
+ visit = it->visitAggregate(InVisit, this);
+ }
+ }
+ }
+ }
+
+ it->decrementDepth();
+ }
+
+ if(visit && it->postVisit)
+ {
+ it->visitAggregate(PostVisit, this);
+ }
+}
+
+//
+// Traverse a selection node. Same comments in binary node apply here.
+//
+void TIntermSelection::traverse(TIntermTraverser* it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitSelection(PreVisit, this);
+
+ if (visit) {
+ it->incrementDepth();
+ if (it->rightToLeft) {
+ if (falseBlock)
+ falseBlock->traverse(it);
+ if (trueBlock)
+ trueBlock->traverse(it);
+ condition->traverse(it);
+ } else {
+ condition->traverse(it);
+ if (trueBlock)
+ trueBlock->traverse(it);
+ if (falseBlock)
+ falseBlock->traverse(it);
+ }
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitSelection(PostVisit, this);
+}
+
+//
+// Traverse a loop node. Same comments in binary node apply here.
+//
+void TIntermLoop::traverse(TIntermTraverser* it)
+{
+ bool visit = true;
+
+ if(it->preVisit)
+ {
+ visit = it->visitLoop(PreVisit, this);
+ }
+
+ if(visit)
+ {
+ it->incrementDepth();
+
+ if(it->rightToLeft)
+ {
+ if(terminal)
+ {
+ terminal->traverse(it);
+ }
+
+ if(body)
+ {
+ body->traverse(it);
+ }
+
+ if(test)
+ {
+ test->traverse(it);
+ }
+ }
+ else
+ {
+ if(test)
+ {
+ test->traverse(it);
+ }
+
+ if(body)
+ {
+ body->traverse(it);
+ }
+
+ if(terminal)
+ {
+ terminal->traverse(it);
+ }
+ }
+
+ it->decrementDepth();
+ }
+
+ if(visit && it->postVisit)
+ {
+ it->visitLoop(PostVisit, this);
+ }
+}
+
+//
+// Traverse a branch node. Same comments in binary node apply here.
+//
+void TIntermBranch::traverse(TIntermTraverser* it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitBranch(PreVisit, this);
+
+ if (visit && expression) {
+ it->incrementDepth();
+ expression->traverse(it);
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitBranch(PostVisit, this);
+}
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/Intermediate.cpp b/Source/ThirdParty/ANGLE/src/compiler/Intermediate.cpp
new file mode 100644
index 0000000..5ebd919
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/Intermediate.cpp
@@ -0,0 +1,1386 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Build the intermediate representation.
+//
+
+#include <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;
+}
+
+////////////////////////////////////////////////////////////////////////////
+//
+// First set of functions are to help build the intermediate representation.
+// These functions are not member functions of the nodes.
+// They are called from parser productions.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+//
+// Add a terminal node for an identifier in an expression.
+//
+// Returns the added node.
+//
+TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line)
+{
+ TIntermSymbol* node = new TIntermSymbol(id, name, type);
+ node->setLine(line);
+
+ return node;
+}
+
+//
+// Connect two nodes with a new parent that does a binary operation on the nodes.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable)
+{
+ switch (op) {
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ if (left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector() || left->getType().getBasicType() == EbtStruct) {
+ return 0;
+ }
+ break;
+ case EOpLogicalOr:
+ case EOpLogicalXor:
+ case EOpLogicalAnd:
+ if (left->getType().getBasicType() != EbtBool || left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector()) {
+ return 0;
+ }
+ break;
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+ case EOpMul:
+ if (left->getType().getBasicType() == EbtStruct || left->getType().getBasicType() == EbtBool)
+ return 0;
+ default: break;
+ }
+
+ //
+ // First try converting the children to compatible types.
+ //
+
+ if (!(left->getType().getStruct() && right->getType().getStruct())) {
+ TIntermTyped* child = addConversion(op, left->getType(), right);
+ if (child)
+ right = child;
+ else {
+ child = addConversion(op, right->getType(), left);
+ if (child)
+ left = child;
+ else
+ return 0;
+ }
+ } else {
+ if (left->getType() != right->getType())
+ return 0;
+ }
+
+
+ //
+ // Need a new node holding things together then. Make
+ // one and promote it to the right type.
+ //
+ TIntermBinary* node = new TIntermBinary(op);
+ if (line == 0)
+ line = right->getLine();
+ node->setLine(line);
+
+ node->setLeft(left);
+ node->setRight(right);
+ if (! node->promote(infoSink))
+ return 0;
+
+ TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
+ TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
+
+ //
+ // See if we can fold constants.
+ //
+
+ TIntermTyped* typedReturnNode = 0;
+ if ( leftTempConstant && rightTempConstant) {
+ typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
+
+ if (typedReturnNode)
+ return typedReturnNode;
+ }
+
+ return node;
+}
+
+//
+// Connect two nodes through an assignment.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
+{
+ //
+ // Like adding binary math, except the conversion can only go
+ // from right to left.
+ //
+ TIntermBinary* node = new TIntermBinary(op);
+ if (line == 0)
+ line = left->getLine();
+ node->setLine(line);
+
+ TIntermTyped* child = addConversion(op, left->getType(), right);
+ if (child == 0)
+ return 0;
+
+ node->setLeft(left);
+ node->setRight(child);
+ if (! node->promote(infoSink))
+ return 0;
+
+ return node;
+}
+
+//
+// Connect two nodes through an index operator, where the left node is the base
+// of an array or struct, and the right node is a direct or indirect offset.
+//
+// Returns the added node.
+// The caller should set the type of the returned node.
+//
+TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line)
+{
+ TIntermBinary* node = new TIntermBinary(op);
+ if (line == 0)
+ line = index->getLine();
+ node->setLine(line);
+ node->setLeft(base);
+ node->setRight(index);
+
+ // caller should set the type
+
+ return node;
+}
+
+//
+// Add one node as the parent of another that it operates on.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable)
+{
+ TIntermUnary* node;
+ TIntermTyped* child = childNode->getAsTyped();
+
+ if (child == 0) {
+ infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
+ return 0;
+ }
+
+ switch (op) {
+ case EOpLogicalNot:
+ if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
+ return 0;
+ }
+ break;
+
+ case EOpPostIncrement:
+ case EOpPreIncrement:
+ case EOpPostDecrement:
+ case EOpPreDecrement:
+ case EOpNegative:
+ if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
+ return 0;
+ default: break;
+ }
+
+ //
+ // Do we need to promote the operand?
+ //
+ // Note: Implicit promotions were removed from the language.
+ //
+ TBasicType newType = EbtVoid;
+ switch (op) {
+ case EOpConstructInt: newType = EbtInt; break;
+ case EOpConstructBool: newType = EbtBool; break;
+ case EOpConstructFloat: newType = EbtFloat; break;
+ default: break;
+ }
+
+ if (newType != EbtVoid) {
+ child = addConversion(op, TType(newType, 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.
+//
+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())
+ return nodePair.node1;
+ else
+ return nodePair.node2;
+ }
+
+ TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
+ node->setLine(line);
+
+ return node;
+}
+
+
+TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
+{
+ if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
+ return right;
+ } else {
+ TIntermTyped *commaAggregate = growAggregate(left, right, line);
+ commaAggregate->getAsAggregate()->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->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(TIntermNode *init, TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, TSourceLoc line)
+{
+ TIntermNode* node = new TIntermLoop(init, body, test, terminal, testFirst);
+ node->setLine(line);
+
+ return node;
+}
+
+//
+// Add branches.
+//
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line)
+{
+ return addBranch(branchOp, 0, line);
+}
+
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line)
+{
+ TIntermBranch* node = new TIntermBranch(branchOp, expression);
+ node->setLine(line);
+
+ return node;
+}
+
+//
+// This is to be executed once the final root is put on top by the parsing
+// process.
+//
+bool TIntermediate::postProcess(TIntermNode* root, EShLanguage language)
+{
+ if (root == 0)
+ return true;
+
+ //
+ // First, finish off the top level sequence, if any
+ //
+ TIntermAggregate* aggRoot = root->getAsAggregate();
+ if (aggRoot && aggRoot->getOp() == EOpNull)
+ aggRoot->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)
+{
+ // 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);
+ }
+
+ //
+ // Array operations.
+ //
+ if (left->isArray() || right->isArray()) {
+ //
+ // Arrays types have to be exact matches.
+ //
+ if (left->getType() != right->getType())
+ return false;
+
+ switch (op) {
+ //
+ // Promote to conditional
+ //
+ case EOpEqual:
+ case EOpNotEqual:
+ setType(TType(EbtBool, EbpUndefined));
+ break;
+
+ //
+ // Set array information.
+ //
+ case EOpAssign:
+ case EOpInitialize:
+ getTypePointer()->setArraySize(left->getType().getArraySize());
+ getTypePointer()->setArrayInformationType(left->getType().getArrayInformationType());
+ break;
+
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ 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;
+ }
+
+ return this;
+}
+
+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());
+}
+
+void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
+{
+ assert(!pragmaTable);
+ pragmaTable = new TPragmaTable();
+ *pragmaTable = pTable;
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/MMap.h b/Source/ThirdParty/ANGLE/src/compiler/MMap.h
new file mode 100644
index 0000000..a308671
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/MMap.h
@@ -0,0 +1,56 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _MMAP_INCLUDED_
+#define _MMAP_INCLUDED_
+
+//
+// Encapsulate memory mapped files
+//
+
+class TMMap {
+public:
+ TMMap(const char* fileName) :
+ fSize(-1), // -1 is the error value returned by GetFileSize()
+ fp(NULL),
+ fBuff(0) // 0 is the error value returned by MapViewOfFile()
+ {
+ if ((fp = fopen(fileName, "r")) == NULL)
+ return;
+ char c = getc(fp);
+ fSize = 0;
+ while (c != EOF) {
+ fSize++;
+ c = getc(fp);
+ }
+ if (c == EOF)
+ fSize++;
+ rewind(fp);
+ fBuff = (char*)malloc(sizeof(char) * fSize);
+ int count = 0;
+ c = getc(fp);
+ while (c != EOF) {
+ fBuff[count++] = c;
+ c = getc(fp);
+ }
+ fBuff[count++] = c;
+ }
+
+ char* getData() { return fBuff; }
+ int getSize() { return fSize; }
+
+ ~TMMap() {
+ if (fp != NULL)
+ fclose(fp);
+ }
+
+private:
+ int fSize; // size of file to map in
+ FILE *fp;
+ char* fBuff; // the actual data;
+};
+
+#endif // _MMAP_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.cpp
new file mode 100644
index 0000000..fd263b6
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.cpp
@@ -0,0 +1,677 @@
+//
+// 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/OutputGLSL.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
+
+TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink)
+ : TIntermTraverser(true, true, true),
+ mObjSink(objSink),
+ mDeclaringVariables(false)
+{
+}
+
+void TOutputGLSL::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 TOutputGLSL::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);
+ out << getTypeName(*fieldType) << " " << fieldType->getFieldName();
+ if (fieldType->isArray())
+ out << arrayBrackets(*fieldType);
+ out << ";\n";
+ }
+ out << "}";
+ mDeclaredStructs.insert(type.getTypeName());
+ }
+ else
+ {
+ out << getTypeName(type);
+ }
+}
+
+void TOutputGLSL::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();
+ TQualifier qualifier = type.getQualifier();
+ // TODO(alokp): Validate qualifier for function arguments.
+ if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
+ out << type.getQualifierString() << " ";
+
+ out << getTypeName(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* TOutputGLSL::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 TOutputGLSL::visitSymbol(TIntermSymbol* node)
+{
+ TInfoSinkBase& out = objSink();
+ out << node->getSymbol();
+
+ if (mDeclaringVariables && node->getType().isArray())
+ out << arrayBrackets(node->getType());
+}
+
+void TOutputGLSL::visitConstantUnion(TIntermConstantUnion* node)
+{
+ writeConstantUnion(node->getType(), node->getUnionArrayPointer());
+}
+
+bool TOutputGLSL::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 TOutputGLSL::visitUnary(Visit visit, TIntermUnary* node)
+{
+ switch (node->getOp())
+ {
+ case EOpNegative: writeTriplet(visit, "(-", NULL, ")"); break;
+ case EOpVectorLogicalNot: writeTriplet(visit, "not(", NULL, ")"); break;
+ case EOpLogicalNot: writeTriplet(visit, "(!", NULL, ")"); break;
+
+ case EOpPostIncrement: writeTriplet(visit, "(", NULL, "++)"); break;
+ case EOpPostDecrement: writeTriplet(visit, "(", NULL, "--)"); break;
+ case EOpPreIncrement: writeTriplet(visit, "(++", NULL, ")"); break;
+ case EOpPreDecrement: writeTriplet(visit, "(--", NULL, ")"); break;
+
+ case EOpConvIntToBool:
+ case EOpConvFloatToBool:
+ switch (node->getOperand()->getType().getNominalSize())
+ {
+ case 1: writeTriplet(visit, "bool(", NULL, ")"); break;
+ case 2: writeTriplet(visit, "bvec2(", NULL, ")"); break;
+ case 3: writeTriplet(visit, "bvec3(", NULL, ")"); break;
+ case 4: writeTriplet(visit, "bvec4(", NULL, ")"); break;
+ default: UNREACHABLE();
+ }
+ break;
+ case EOpConvBoolToFloat:
+ case EOpConvIntToFloat:
+ switch (node->getOperand()->getType().getNominalSize())
+ {
+ case 1: writeTriplet(visit, "float(", NULL, ")"); break;
+ case 2: writeTriplet(visit, "vec2(", NULL, ")"); break;
+ case 3: writeTriplet(visit, "vec3(", NULL, ")"); break;
+ case 4: writeTriplet(visit, "vec4(", NULL, ")"); break;
+ default: UNREACHABLE();
+ }
+ break;
+ case EOpConvFloatToInt:
+ case EOpConvBoolToInt:
+ switch (node->getOperand()->getType().getNominalSize())
+ {
+ case 1: writeTriplet(visit, "int(", NULL, ")"); break;
+ case 2: writeTriplet(visit, "ivec2(", NULL, ")"); break;
+ case 3: writeTriplet(visit, "ivec3(", NULL, ")"); break;
+ case 4: writeTriplet(visit, "ivec4(", NULL, ")"); break;
+ default: UNREACHABLE();
+ }
+ break;
+
+ case EOpRadians: writeTriplet(visit, "radians(", NULL, ")"); break;
+ case EOpDegrees: writeTriplet(visit, "degrees(", NULL, ")"); break;
+ case EOpSin: writeTriplet(visit, "sin(", NULL, ")"); break;
+ case EOpCos: writeTriplet(visit, "cos(", NULL, ")"); break;
+ case EOpTan: writeTriplet(visit, "tan(", NULL, ")"); break;
+ case EOpAsin: writeTriplet(visit, "asin(", NULL, ")"); break;
+ case EOpAcos: writeTriplet(visit, "acos(", NULL, ")"); break;
+ case EOpAtan: writeTriplet(visit, "atan(", NULL, ")"); break;
+
+ case EOpExp: writeTriplet(visit, "exp(", NULL, ")"); break;
+ case EOpLog: writeTriplet(visit, "log(", NULL, ")"); break;
+ case EOpExp2: writeTriplet(visit, "exp2(", NULL, ")"); break;
+ case EOpLog2: writeTriplet(visit, "log2(", NULL, ")"); break;
+ case EOpSqrt: writeTriplet(visit, "sqrt(", NULL, ")"); break;
+ case EOpInverseSqrt: writeTriplet(visit, "inversesqrt(", NULL, ")"); break;
+
+ case EOpAbs: writeTriplet(visit, "abs(", NULL, ")"); break;
+ case EOpSign: writeTriplet(visit, "sign(", NULL, ")"); break;
+ case EOpFloor: writeTriplet(visit, "floor(", NULL, ")"); break;
+ case EOpCeil: writeTriplet(visit, "ceil(", NULL, ")"); break;
+ case EOpFract: writeTriplet(visit, "fract(", NULL, ")"); break;
+
+ case EOpLength: writeTriplet(visit, "length(", NULL, ")"); break;
+ case EOpNormalize: writeTriplet(visit, "normalize(", NULL, ")"); break;
+
+ case EOpAny: writeTriplet(visit, "any(", NULL, ")"); break;
+ case EOpAll: writeTriplet(visit, "all(", NULL, ")"); break;
+
+ default: UNREACHABLE(); break;
+ }
+
+ return true;
+}
+
+bool TOutputGLSL::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 TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+ bool visitChildren = true;
+ TInfoSinkBase& out = objSink();
+ 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);
+ TString returnType = getTypeName(node->getType());
+ out << returnType << " " << node->getName();
+
+ out << "(";
+ writeFunctionParameters(node->getSequence());
+ out << ")";
+
+ visitChildren = false;
+ break;
+ }
+ case EOpFunction: {
+ // Function definition.
+ ASSERT(visit == PreVisit);
+ TString returnType = getTypeName(node->getType());
+ TString functionName = TFunction::unmangleName(node->getName());
+ out << returnType << " " << functionName;
+
+ 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: writeTriplet(visit, "lessThan(", ", ", ")"); break;
+ case EOpGreaterThan: writeTriplet(visit, "greaterThan(", ", ", ")"); break;
+ case EOpLessThanEqual: writeTriplet(visit, "lessThanEqual(", ", ", ")"); break;
+ case EOpGreaterThanEqual: writeTriplet(visit, "greaterThanEqual(", ", ", ")"); break;
+ case EOpVectorEqual: writeTriplet(visit, "equal(", ", ", ")"); break;
+ case EOpVectorNotEqual: writeTriplet(visit, "notEqual(", ", ", ")"); break;
+ case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break;
+
+ case EOpMod: writeTriplet(visit, "mod(", ", ", ")"); break;
+ case EOpPow: writeTriplet(visit, "pow(", ", ", ")"); break;
+ case EOpAtan: writeTriplet(visit, "atan(", ", ", ")"); break;
+ case EOpMin: writeTriplet(visit, "min(", ", ", ")"); break;
+ case EOpMax: writeTriplet(visit, "max(", ", ", ")"); break;
+ case EOpClamp: writeTriplet(visit, "clamp(", ", ", ")"); break;
+ case EOpMix: writeTriplet(visit, "mix(", ", ", ")"); break;
+ case EOpStep: writeTriplet(visit, "step(", ", ", ")"); break;
+ case EOpSmoothStep: writeTriplet(visit, "smoothstep(", ", ", ")"); break;
+
+ case EOpDistance: writeTriplet(visit, "distance(", ", ", ")"); break;
+ case EOpDot: writeTriplet(visit, "dot(", ", ", ")"); break;
+ case EOpCross: writeTriplet(visit, "cross(", ", ", ")"); break;
+ case EOpFaceForward: writeTriplet(visit, "faceforward(", ", ", ")"); break;
+ case EOpReflect: writeTriplet(visit, "reflect(", ", ", ")"); break;
+ case EOpRefract: writeTriplet(visit, "refract(", ", ", ")"); break;
+ case EOpMul: writeTriplet(visit, "matrixCompMult(", ", ", ")"); break;
+
+ default: UNREACHABLE(); break;
+ }
+ return visitChildren;
+}
+
+bool TOutputGLSL::visitLoop(Visit visit, TIntermLoop* node)
+{
+ TInfoSinkBase& out = objSink();
+
+ incrementDepth();
+ // Loop header.
+ if (node->testFirst()) // for loop
+ {
+ out << "for (";
+ if (node->getInit())
+ node->getInit()->traverse(this);
+ out << "; ";
+
+ ASSERT(node->getTest() != NULL);
+ node->getTest()->traverse(this);
+ out << "; ";
+
+ if (node->getTerminal())
+ node->getTerminal()->traverse(this);
+ out << ")\n";
+ }
+ else // do-while loop
+ {
+ out << "do\n";
+ }
+
+ // Loop body.
+ visitCodeBlock(node->getBody());
+
+ // Loop footer.
+ if (!node->testFirst()) // while loop
+ {
+ out << "while (";
+ ASSERT(node->getTest() != NULL);
+ node->getTest()->traverse(this);
+ out << ");\n";
+ }
+ decrementDepth();
+
+ // No need to visit children. They have been already processed in
+ // this function.
+ return false;
+}
+
+bool TOutputGLSL::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 TOutputGLSL::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/Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.h b/Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.h
new file mode 100644
index 0000000..aa203d4
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.h
@@ -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.
+//
+
+#ifndef CROSSCOMPILERGLSL_OUTPUTGLSL_H_
+#define CROSSCOMPILERGLSL_OUTPUTGLSL_H_
+
+#include <set>
+
+#include "compiler/intermediate.h"
+#include "compiler/ParseHelper.h"
+
+class TOutputGLSL : public TIntermTraverser
+{
+public:
+ TOutputGLSL(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);
+ 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;
+};
+
+#endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp
new file mode 100644
index 0000000..8b8a4e6
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp
@@ -0,0 +1,2160 @@
+//
+// 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/OutputHLSL.h"
+
+#include "compiler/debug.h"
+#include "compiler/InfoSink.h"
+#include "compiler/UnfoldSelect.h"
+
+#include <stdio.h>
+#include <algorithm>
+
+namespace sh
+{
+// Integer to TString conversion
+TString str(int i)
+{
+ char buffer[20];
+ sprintf(buffer, "%d", i);
+ return buffer;
+}
+
+OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, true), mContext(context)
+{
+ mUnfoldSelect = new UnfoldSelect(context, this);
+ mInsideFunction = false;
+
+ mUsesTexture2D = false;
+ mUsesTexture2D_bias = false;
+ mUsesTexture2DProj = false;
+ mUsesTexture2DProj_bias = false;
+ mUsesTextureCube = false;
+ mUsesTextureCube_bias = false;
+ mUsesDepthRange = false;
+ mUsesFragCoord = false;
+ mUsesPointCoord = false;
+ mUsesFrontFacing = false;
+ mUsesPointSize = false;
+ mUsesXor = false;
+ mUsesMod1 = false;
+ mUsesMod2 = false;
+ mUsesMod3 = false;
+ mUsesMod4 = 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 = false;
+
+ mScopeDepth = 0;
+
+ mArgumentIndex = 0;
+}
+
+OutputHLSL::~OutputHLSL()
+{
+ delete mUnfoldSelect;
+}
+
+void OutputHLSL::output()
+{
+ 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()
+{
+ EShLanguage language = mContext.language;
+ 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 (language == EShLangFragment)
+ {
+ 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) + " " + decorate(name) + 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_Viewport;\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";
+ }
+ }
+ 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) + " " + decorate(name) + 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 (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 gl_DepthRangeParameters gl_DepthRange;\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 (mUsesMod2)
+ {
+ out << "float2 mod(float2 x, float y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"
+ "\n";
+ }
+
+ if (mUsesMod3)
+ {
+ out << "float3 mod(float3 x, float y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"
+ "\n";
+ }
+
+ if (mUsesMod4)
+ {
+ 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)
+ {
+ 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";
+ }
+}
+
+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());
+ }
+ else if (qualifier == EvqAttribute)
+ {
+ mReferencedAttributes.insert(name.c_str());
+ }
+ else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut || qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn)
+ {
+ mReferencedVaryings.insert(name.c_str());
+ }
+
+ out << decorate(name);
+ }
+}
+
+bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
+{
+ TInfoSinkBase &out = mBody;
+
+ switch (node->getOp())
+ {
+ case EOpAssign: outputTriplet(visit, "(", " = ", ")"); break;
+ case EOpInitialize: outputTriplet(visit, "", " = ", ""); 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 << "." + node->getType().getFieldName();
+
+ 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 << "." + fieldType->getFieldName() + " == ";
+ node->getRight()->traverse(this);
+ out << "." + fieldType->getFieldName();
+
+ 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: outputTriplet(visit, "(", " || ", ")"); break;
+ case EOpLogicalXor:
+ mUsesXor = true;
+ outputTriplet(visit, "xor(", ", ", ")");
+ break;
+ case EOpLogicalAnd: outputTriplet(visit, "(", " && ", ")"); break;
+ default: UNREACHABLE();
+ }
+
+ return true;
+}
+
+bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
+{
+ TInfoSinkBase &out = mBody;
+
+ 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 EOpDPdx: outputTriplet(visit, "ddx(", "", ")"); break;
+// case EOpDPdy: outputTriplet(visit, "ddy(", "", ")"); break;
+// case EOpFwidth: 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)
+{
+ EShLanguage language = mContext.language;
+ TInfoSinkBase &out = mBody;
+
+ switch (node->getOp())
+ {
+ case EOpSequence:
+ {
+ if (mInsideFunction)
+ {
+ 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++)
+ {
+ if (isSingleStatement(*sit))
+ {
+ mUnfoldSelect->traverse(*sit);
+ }
+
+ (*sit)->traverse(this);
+
+ out << ";\n";
+ }
+
+ if (mInsideFunction)
+ {
+ 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()) << "(";
+
+ 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";
+
+ return false;
+ }
+ break;
+ case EOpComma: outputTriplet(visit, "", ", ", ""); break;
+ case EOpFunction:
+ {
+ TString name = TFunction::unmangleName(node->getName());
+
+ if (visit == PreVisit)
+ {
+ out << typeString(node->getType()) << " ";
+
+ if (name == "main")
+ {
+ out << "gl_main(";
+ }
+ else
+ {
+ out << decorate(name) << "(";
+ }
+
+ TIntermSequence &sequence = node->getSequence();
+ TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence();
+
+ for (unsigned int i = 0; i < arguments.size(); i++)
+ {
+ TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
+
+ if (symbol)
+ {
+ out << argumentString(symbol);
+
+ if (i < arguments.size() - 1)
+ {
+ out << ", ";
+ }
+ }
+ else UNREACHABLE();
+ }
+
+ sequence.erase(sequence.begin());
+
+ out << ")\n"
+ "{\n";
+
+ mInsideFunction = true;
+ }
+ else if (visit == PostVisit)
+ {
+ out << "}\n";
+
+ mInsideFunction = false;
+ }
+ }
+ break;
+ case EOpFunctionCall:
+ {
+ if (visit == PreVisit)
+ {
+ TString name = TFunction::unmangleName(node->getName());
+
+ if (node->isUserDefined())
+ {
+ out << decorate(name) << "(";
+ }
+ else
+ {
+ if (name == "texture2D")
+ {
+ if (node->getSequence().size() == 2)
+ {
+ mUsesTexture2D = true;
+ }
+ else if (node->getSequence().size() == 3)
+ {
+ mUsesTexture2D_bias = true;
+ }
+ else UNREACHABLE();
+
+ out << "gl_texture2D(";
+ }
+ else if (name == "texture2DProj")
+ {
+ if (node->getSequence().size() == 2)
+ {
+ mUsesTexture2DProj = true;
+ }
+ else if (node->getSequence().size() == 3)
+ {
+ mUsesTexture2DProj_bias = true;
+ }
+ else UNREACHABLE();
+
+ out << "gl_texture2DProj(";
+ }
+ else if (name == "textureCube")
+ {
+ if (node->getSequence().size() == 2)
+ {
+ mUsesTextureCube = true;
+ }
+ else if (node->getSequence().size() == 3)
+ {
+ mUsesTextureCube_bias = true;
+ }
+ else UNREACHABLE();
+
+ out << "gl_textureCube(";
+ }
+ else if (name == "texture2DLod")
+ {
+ UNIMPLEMENTED(); // Requires the vertex shader texture sampling extension
+ }
+ else if (name == "texture2DProjLod")
+ {
+ UNIMPLEMENTED(); // Requires the vertex shader texture sampling extension
+ }
+ else if (name == "textureCubeLod")
+ {
+ UNIMPLEMENTED(); // Requires the vertex shader texture sampling extension
+ }
+ 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:
+ {
+ switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) // Number of components in the first argument
+ {
+ case 1: mUsesMod1 = true; break;
+ case 2: mUsesMod2 = true; break;
+ case 3: mUsesMod3 = true; break;
+ case 4: mUsesMod4 = 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
+ mUsesAtan2 = true;
+ 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 << "t" << mUnfoldSelect->getTemporaryIndex();
+ }
+ else // if/else statement
+ {
+ mUnfoldSelect->traverse(node->getCondition());
+
+ out << "if(";
+
+ node->getCondition()->traverse(this);
+
+ out << ")\n"
+ "{\n";
+
+ if (node->getTrueBlock())
+ {
+ node->getTrueBlock()->traverse(this);
+ }
+
+ out << ";}\n";
+
+ if (node->getFalseBlock())
+ {
+ out << "else\n"
+ "{\n";
+
+ node->getFalseBlock()->traverse(this);
+
+ out << ";}\n";
+ }
+ }
+
+ return false;
+}
+
+void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node)
+{
+ writeConstantUnion(node->getType(), node->getUnionArrayPointer());
+}
+
+bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
+{
+ if (handleExcessiveLoop(node))
+ {
+ return false;
+ }
+
+ TInfoSinkBase &out = mBody;
+
+ if (!node->testFirst())
+ {
+ out << "do\n"
+ "{\n";
+ }
+ else
+ {
+ if (node->getInit())
+ {
+ mUnfoldSelect->traverse(node->getInit());
+ }
+
+ if (node->getTest())
+ {
+ mUnfoldSelect->traverse(node->getTest());
+ }
+
+ if (node->getTerminal())
+ {
+ mUnfoldSelect->traverse(node->getTerminal());
+ }
+
+ out << "for(";
+
+ if (node->getInit())
+ {
+ node->getInit()->traverse(this);
+ }
+
+ out << "; ";
+
+ if (node->getTest())
+ {
+ node->getTest()->traverse(this);
+ }
+
+ out << "; ";
+
+ if (node->getTerminal())
+ {
+ node->getTerminal()->traverse(this);
+ }
+
+ out << ")\n"
+ "{\n";
+ }
+
+ if (node->getBody())
+ {
+ node->getBody()->traverse(this);
+ }
+
+ out << "}\n";
+
+ if (!node->testFirst())
+ {
+ out << "while(\n";
+
+ node->getTest()->traverse(this);
+
+ out << ")";
+ }
+
+ out << ";\n";
+
+ return false;
+}
+
+bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
+{
+ TInfoSinkBase &out = mBody;
+
+ switch (node->getFlowOp())
+ {
+ case EOpKill: outputTriplet(visit, "discard", "", ""); break;
+ case EOpBreak: outputTriplet(visit, "break", "", ""); break;
+ case EOpContinue: outputTriplet(visit, "continue", "", ""); break;
+ case EOpReturn:
+ if (visit == PreVisit)
+ {
+ if (node->getExpression())
+ {
+ out << "return ";
+ }
+ else
+ {
+ out << "return;\n";
+ }
+ }
+ else if (visit == PostVisit)
+ {
+ out << ";\n";
+ }
+ break;
+ default: UNREACHABLE();
+ }
+
+ return true;
+}
+
+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 255 iterations (unsupported by D3D9) by splitting them
+bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
+{
+ 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->getTest())
+ {
+ TIntermBinary *test = node->getTest()->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->getTerminal())
+ {
+ TIntermBinary *binaryTerminal = node->getTerminal()->getAsBinaryNode();
+ TIntermUnary *unaryTerminal = node->getTerminal()->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 + 1) / increment;
+
+ if (iterations <= 255)
+ {
+ return false; // Not an excessive loop
+ }
+
+ while (iterations > 0)
+ {
+ int remainder = (limit - initial + 1) % increment;
+ int clampedLimit = initial + increment * std::min(255, iterations) - 1 - remainder;
+
+ // for(int index = initial; index < clampedLimit; index += increment)
+
+ out << "for(int ";
+ index->traverse(this);
+ out << " = ";
+ out << initial;
+
+ out << "; ";
+ index->traverse(this);
+ out << " < ";
+ out << clampedLimit;
+
+ out << "; ";
+ index->traverse(this);
+ out << " += ";
+ out << increment;
+ out << ")\n"
+ "{\n";
+
+ if (node->getBody())
+ {
+ node->getBody()->traverse(this);
+ }
+
+ out << "}\n";
+
+ initial += 255 * increment;
+ iterations -= 255;
+ }
+
+ 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;
+ }
+}
+
+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(mArgumentIndex++);
+ }
+ 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) + " " + 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";
+ }
+ }
+
+ 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
+ }
+
+ 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 (parameters)
+ {
+ for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++)
+ {
+ ctorParameters.push_back((*parameter)->getAsTyped()->getType());
+ }
+ }
+ else 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) + " " + field.getFieldName() + 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 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.substr(0, 3) != "gl_" && string.substr(0, 3) != "dx_")
+ {
+ return "_" + string;
+ }
+ else
+ {
+ return string;
+ }
+}
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.h b/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.h
new file mode 100644
index 0000000..dc3c482
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.h
@@ -0,0 +1,127 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_OUTPUTHLSL_H_
+#define COMPILER_OUTPUTHLSL_H_
+
+#include <list>
+#include <set>
+
+#include "compiler/intermediate.h"
+#include "compiler/ParseHelper.h"
+
+namespace sh
+{
+class UnfoldSelect;
+
+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); // Prepend an underscore to avoid naming clashes
+
+ 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*);
+
+ bool isSingleStatement(TIntermNode *node);
+ bool handleExcessiveLoop(TIntermLoop *node);
+ void outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString);
+ 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;
+ UnfoldSelect *mUnfoldSelect;
+ 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 mUsesTexture2DProj;
+ bool mUsesTexture2DProj_bias;
+ bool mUsesTextureCube;
+ bool mUsesTextureCube_bias;
+ bool mUsesDepthRange;
+ bool mUsesFragCoord;
+ bool mUsesPointCoord;
+ bool mUsesFrontFacing;
+ bool mUsesPointSize;
+ bool mUsesXor;
+ bool mUsesMod1;
+ bool mUsesMod2;
+ bool mUsesMod3;
+ bool mUsesMod4;
+ 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;
+
+ 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 mArgumentIndex; // For creating unique argument names
+};
+}
+
+#endif // COMPILER_OUTPUTHLSL_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/ParseHelper.cpp b/Source/ThirdParty/ANGLE/src/compiler/ParseHelper.cpp
new file mode 100644
index 0000000..407226b
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/ParseHelper.cpp
@@ -0,0 +1,1479 @@
+//
+// 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"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "compiler/osinclude.h"
+#include "compiler/InitializeParseContext.h"
+
+///////////////////////////////////////////////////////////////////////
+//
+// Sub- vector and matrix fields
+//
+////////////////////////////////////////////////////////////////////////
+
+//
+// Look at a '.' field selector string and change it into offsets
+// for a vector.
+//
+bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line)
+{
+ fields.num = (int) compString.size();
+ if (fields.num > 4) {
+ error(line, "illegal vector field selection", compString.c_str(), "");
+ return false;
+ }
+
+ enum {
+ exyzw,
+ ergba,
+ estpq,
+ } fieldSet[4];
+
+ for (int i = 0; i < fields.num; ++i) {
+ switch (compString[i]) {
+ case 'x':
+ fields.offsets[i] = 0;
+ fieldSet[i] = exyzw;
+ break;
+ case 'r':
+ fields.offsets[i] = 0;
+ fieldSet[i] = ergba;
+ break;
+ case 's':
+ fields.offsets[i] = 0;
+ fieldSet[i] = estpq;
+ break;
+ case 'y':
+ fields.offsets[i] = 1;
+ fieldSet[i] = exyzw;
+ break;
+ case 'g':
+ fields.offsets[i] = 1;
+ fieldSet[i] = ergba;
+ break;
+ case 't':
+ fields.offsets[i] = 1;
+ fieldSet[i] = estpq;
+ break;
+ case 'z':
+ fields.offsets[i] = 2;
+ fieldSet[i] = exyzw;
+ break;
+ case 'b':
+ fields.offsets[i] = 2;
+ fieldSet[i] = ergba;
+ break;
+ case 'p':
+ fields.offsets[i] = 2;
+ fieldSet[i] = estpq;
+ break;
+
+ case 'w':
+ fields.offsets[i] = 3;
+ fieldSet[i] = exyzw;
+ break;
+ case 'a':
+ fields.offsets[i] = 3;
+ fieldSet[i] = ergba;
+ break;
+ case 'q':
+ fields.offsets[i] = 3;
+ fieldSet[i] = estpq;
+ break;
+ default:
+ error(line, "illegal vector field selection", compString.c_str(), "");
+ return false;
+ }
+ }
+
+ for (int i = 0; i < fields.num; ++i) {
+ if (fields.offsets[i] >= vecSize) {
+ error(line, "vector field selection out of range", compString.c_str(), "");
+ return false;
+ }
+
+ if (i > 0) {
+ if (fieldSet[i] != fieldSet[i-1]) {
+ error(line, "illegal - vector component fields not from the same set", compString.c_str(), "");
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+//
+// Look at a '.' field selector string and change it into offsets
+// for a matrix.
+//
+bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, int line)
+{
+ fields.wholeRow = false;
+ fields.wholeCol = false;
+ fields.row = -1;
+ fields.col = -1;
+
+ if (compString.size() != 2) {
+ error(line, "illegal length of matrix field selection", compString.c_str(), "");
+ return false;
+ }
+
+ if (compString[0] == '_') {
+ if (compString[1] < '0' || compString[1] > '3') {
+ error(line, "illegal matrix field selection", compString.c_str(), "");
+ return false;
+ }
+ fields.wholeCol = true;
+ fields.col = compString[1] - '0';
+ } else if (compString[1] == '_') {
+ if (compString[0] < '0' || compString[0] > '3') {
+ error(line, "illegal matrix field selection", compString.c_str(), "");
+ return false;
+ }
+ fields.wholeRow = true;
+ fields.row = compString[0] - '0';
+ } else {
+ if (compString[0] < '0' || compString[0] > '3' ||
+ compString[1] < '0' || compString[1] > '3') {
+ error(line, "illegal matrix field selection", compString.c_str(), "");
+ return false;
+ }
+ fields.row = compString[0] - '0';
+ fields.col = compString[1] - '0';
+ }
+
+ if (fields.row >= matSize || fields.col >= matSize) {
+ error(line, "matrix field selection out of range", compString.c_str(), "");
+ return false;
+ }
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// Errors
+//
+////////////////////////////////////////////////////////////////////////
+
+//
+// Track whether errors have occurred.
+//
+void TParseContext::recover()
+{
+ recoveredFromError = true;
+}
+
+//
+// Used by flex/bison to output all syntax and parsing errors.
+//
+void TParseContext::error(TSourceLoc nLine, const char *szReason, const char *szToken,
+ const char *szExtraInfoFormat, ...)
+{
+ char szExtraInfo[400];
+ va_list marker;
+
+ va_start(marker, szExtraInfoFormat);
+
+ vsnprintf(szExtraInfo, sizeof(szExtraInfo), szExtraInfoFormat, marker);
+
+ /* VC++ format: file(linenum) : error #: 'token' : extrainfo */
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info.location(nLine);
+ infoSink.info << "'" << szToken << "' : " << szReason << " " << szExtraInfo << "\n";
+
+ va_end(marker);
+
+ ++numErrors;
+}
+
+//
+// Same error message for all places assignments don't work.
+//
+void TParseContext::assignError(int line, const char* op, TString left, TString right)
+{
+ error(line, "", op, "cannot convert from '%s' to '%s'",
+ right.c_str(), left.c_str());
+}
+
+//
+// Same error message for all places unary operations don't work.
+//
+void TParseContext::unaryOpError(int line, const char* op, TString operand)
+{
+ error(line, " wrong operand type", op,
+ "no operation '%s' exists that takes an operand of type %s (or there is no acceptable conversion)",
+ op, operand.c_str());
+}
+
+//
+// Same error message for all binary operations don't work.
+//
+void TParseContext::binaryOpError(int line, const char* op, TString left, TString right)
+{
+ error(line, " wrong operand types ", op,
+ "no operation '%s' exists that takes a left-hand operand of type '%s' and "
+ "a right operand of type '%s' (or there is no acceptable conversion)",
+ op, left.c_str(), right.c_str());
+}
+
+bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicType type){
+ 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;
+ }
+ 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)
+ error(line, " l-value required", op, "\"%s\" (%s)", symbol, message);
+ else
+ error(line, " l-value required", op, "(%s)", message);
+
+ return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if the node is really
+// a constant.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::constErrorCheck(TIntermTyped* node)
+{
+ if (node->getQualifier() == EvqConst)
+ return false;
+
+ error(node->getLine(), "constant expression required", "", "");
+
+ return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if the node is really
+// an integer.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
+{
+ if (node->getBasicType() == EbtInt && node->getNominalSize() == 1)
+ return false;
+
+ error(node->getLine(), "integer expression required", token, "");
+
+ return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if we are currently
+// globally scoped.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::globalErrorCheck(int line, bool global, const char* token)
+{
+ if (global)
+ return false;
+
+ error(line, "only allowed at global scope", token, "");
+
+ return true;
+}
+
+//
+// For now, keep it simple: if it starts "gl_", it's reserved, independent
+// of scope. Except, if the symbol table is at the built-in push-level,
+// which is when we are parsing built-ins.
+// 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.substr(0, 3) == TString("gl_")) {
+ error(line, reservedErrMsg, "gl_", "");
+ return true;
+ }
+ if (spec == EShSpecWebGL) {
+ if (identifier.substr(0, 6) == TString("webgl_")) {
+ error(line, reservedErrMsg, "webgl_", "");
+ return true;
+ }
+ if (identifier.substr(0, 7) == TString("_webgl_")) {
+ error(line, reservedErrMsg, "_webgl_", "");
+ return true;
+ }
+ }
+ if (identifier.find("__") != TString::npos) {
+ //error(line, "Two consecutive underscores are reserved for future use.", identifier.c_str(), "", "");
+ //return true;
+ infoSink.info.message(EPrefixWarning, "Two consecutive underscores are reserved for future use.", line);
+ return false;
+ }
+ }
+
+ return false;
+}
+
+//
+// Make sure there is enough data provided to the constructor to build
+// something of the type of the constructor. Also returns the type of
+// the constructor.
+//
+// Returns true if there was an error in construction.
+//
+bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
+{
+ *type = function.getReturnType();
+
+ bool constructingMatrix = false;
+ switch(op) {
+ case EOpConstructMat2:
+ case EOpConstructMat3:
+ case EOpConstructMat4:
+ constructingMatrix = true;
+ break;
+ default:
+ break;
+ }
+
+ //
+ // Note: It's okay to have too many components available, but not okay to have unused
+ // arguments. 'full' will go to true when enough args have been seen. If we loop
+ // again, there is an extra argument, so 'overfull' will become true.
+ //
+
+ int size = 0;
+ bool constType = true;
+ bool full = false;
+ bool overFull = false;
+ bool matrixInMatrix = false;
+ bool arrayArg = false;
+ for (int i = 0; i < function.getParamCount(); ++i) {
+ size += function[i].type->getObjectSize();
+
+ if (constructingMatrix && function[i].type->isMatrix())
+ matrixInMatrix = true;
+ if (full)
+ overFull = true;
+ if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
+ full = true;
+ if (function[i].type->getQualifier() != EvqConst)
+ constType = false;
+ if (function[i].type->isArray())
+ arrayArg = true;
+ }
+
+ if (constType)
+ type->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() && 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()) {
+ if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
+ (op == EOpConstructStruct && size < type->getObjectSize())) {
+ error(line, "not enough data provided for construction", "constructor", "");
+ return true;
+ }
+ }
+
+ TIntermTyped* typed = node->getAsTyped();
+ if (typed == 0) {
+ error(line, "constructor argument does not have a type", "constructor", "");
+ return true;
+ }
+ if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
+ error(line, "cannot convert a sampler", "constructor", "");
+ return true;
+ }
+ if (typed->getBasicType() == EbtVoid) {
+ error(line, "cannot convert a void", "constructor", "");
+ return true;
+ }
+
+ return false;
+}
+
+// This function checks to see if a void variable has been declared and raise an error message for such a case
+//
+// returns true in case of an error
+//
+bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType)
+{
+ if (pubType.type == EbtVoid) {
+ error(line, "illegal use of type 'void'", identifier.c_str(), "");
+ return true;
+ }
+
+ return false;
+}
+
+// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
+//
+// returns true in case of an error
+//
+bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
+{
+ if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
+ error(line, "boolean expression expected", "", "");
+ return true;
+ }
+
+ return false;
+}
+
+// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
+//
+// returns true in case of an error
+//
+bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
+{
+ if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
+ error(line, "boolean expression expected", "", "");
+ return true;
+ }
+
+ return false;
+}
+
+bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason)
+{
+ if (pType.type == EbtStruct) {
+ if (containsSampler(*pType.userDef)) {
+ error(line, reason, 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) {
+ error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str(), "");
+ return true;
+ }
+
+ if (type.qualifier == EvqConst && extensionErrorCheck(line, "GL_3DL_array_objects"))
+ return true;
+
+ return false;
+}
+
+//
+// See if this type can be an array.
+//
+// Returns true if there is an error.
+//
+bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type)
+{
+ //
+ // Can the type be an array?
+ //
+ if (type.array) {
+ error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str(), "");
+ return true;
+ }
+
+ return false;
+}
+
+//
+// Do all the semantic checking for declaring an array, with and
+// without a size, and make the right changes to the symbol table.
+//
+// size == 0 means no specified size.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable)
+{
+ //
+ // Don't check for reserved word use until after we know it's not in the symbol table,
+ // because reserved arrays can be redeclared.
+ //
+
+ bool builtIn = false;
+ bool sameScope = false;
+ TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope);
+ if (symbol == 0 || !sameScope) {
+ if (reservedErrorCheck(line, identifier))
+ return true;
+
+ variable = new TVariable(&identifier, TType(type));
+
+ if (type.arraySize)
+ variable->getType().setArraySize(type.arraySize);
+
+ if (! symbolTable.insert(*variable)) {
+ delete variable;
+ error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str(), "");
+ return true;
+ }
+ } else {
+ if (! symbol->isVariable()) {
+ error(line, "variable expected", identifier.c_str(), "");
+ return true;
+ }
+
+ variable = static_cast<TVariable*>(symbol);
+ if (! variable->getType().isArray()) {
+ error(line, "redeclaring non-array as array", identifier.c_str(), "");
+ return true;
+ }
+ if (variable->getType().getArraySize() > 0) {
+ error(line, "redeclaration of array with size", identifier.c_str(), "");
+ return true;
+ }
+
+ if (! variable->getType().sameElementType(TType(type))) {
+ error(line, "redeclaration of array with a different type", identifier.c_str(), "");
+ return true;
+ }
+
+ TType* t = variable->getArrayInformationType();
+ while (t != 0) {
+ if (t->getMaxArraySize() > type.arraySize) {
+ error(line, "higher index value already used for the array", identifier.c_str(), "");
+ return true;
+ }
+ t->setArraySize(type.arraySize);
+ t = t->getArrayInformationType();
+ }
+
+ if (type.arraySize)
+ variable->getType().setArraySize(type.arraySize);
+ }
+
+ if (voidErrorCheck(line, identifier, type))
+ return true;
+
+ return false;
+}
+
+bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
+{
+ bool builtIn = false;
+ TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn);
+ if (symbol == 0) {
+ error(line, " undeclared identifier", node->getSymbol().c_str(), "");
+ return true;
+ }
+ TVariable* variable = static_cast<TVariable*>(symbol);
+
+ type->setArrayInformationType(variable->getArrayInformationType());
+ variable->updateArrayInformationType(type);
+
+ // special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers
+ // its an error
+ if (node->getSymbol() == "gl_FragData") {
+ TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", &builtIn);
+ if (fragData == 0) {
+ infoSink.info.message(EPrefixInternalError, "gl_MaxDrawBuffers not defined", line);
+ return true;
+ }
+
+ int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst();
+ if (fragDataValue <= size) {
+ error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers", "");
+ return true;
+ }
+ }
+
+ // we dont want to update the maxArraySize when this flag is not set, we just want to include this
+ // node type in the chain of node types so that its updated when a higher maxArraySize comes in.
+ if (!updateFlag)
+ return false;
+
+ size++;
+ variable->getType().setMaxArraySize(size);
+ type->setMaxArraySize(size);
+ TType* tt = type;
+
+ while(tt->getArrayInformationType() != 0) {
+ tt = tt->getArrayInformationType();
+ tt->setMaxArraySize(size);
+ }
+
+ return false;
+}
+
+//
+// Enforce non-initializer type/qualifier rules.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type)
+{
+ //
+ // Make the qualifier make sense.
+ //
+ if (type.qualifier == EvqConst) {
+ type.qualifier = EvqTemporary;
+ error(line, "variables with qualifier 'const' must be initialized", identifier.c_str(), "");
+ return true;
+ }
+
+ return false;
+}
+
+//
+// Do semantic checking for a variable declaration that has no initializer,
+// and update the symbol table.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type)
+{
+ if (reservedErrorCheck(line, identifier))
+ recover();
+
+ TVariable* variable = new TVariable(&identifier, TType(type));
+
+ if (! symbolTable.insert(*variable)) {
+ error(line, "redefinition", variable->getName().c_str(), "");
+ delete variable;
+ return true;
+ }
+
+ if (voidErrorCheck(line, identifier, type))
+ return true;
+
+ return false;
+}
+
+bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
+{
+ if (qualifier != EvqConst && qualifier != EvqTemporary) {
+ error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier), "");
+ return true;
+ }
+ if (qualifier == EvqConst && paramQualifier != EvqIn) {
+ error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
+ return true;
+ }
+
+ if (qualifier == EvqConst)
+ type->setQualifier(EvqConstReadOnly);
+ else
+ type->setQualifier(paramQualifier);
+
+ return false;
+}
+
+bool TParseContext::extensionErrorCheck(int line, const char* extension)
+{
+ if (extensionBehavior[extension] == EBhWarn) {
+ infoSink.info.message(EPrefixWarning, ("extension " + TString(extension) + " is being used").c_str(), line);
+ return false;
+ }
+ if (extensionBehavior[extension] == EBhDisable) {
+ error(line, "extension", extension, "is disabled");
+ return true;
+ }
+
+ return false;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Non-Errors.
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+//
+// Look up a function name in the symbol table, and make sure it is a function.
+//
+// Return the function symbol if found, otherwise 0.
+//
+const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn)
+{
+ // 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()) {
+ error(line, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().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 {
+ error(line, " cannot assign to", "=", "'%s'", variable->getType().getCompleteString().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)
+{
+ if (!aggrNode->isConstructor())
+ return false;
+
+ bool allConstant = true;
+
+ // check if all the child nodes are constants so that they can be inserted into
+ // the parent node
+ if (aggrNode) {
+ TIntermSequence &childSequenceVector = aggrNode->getSequence() ;
+ for (TIntermSequence::iterator p = childSequenceVector.begin();
+ p != childSequenceVector.end(); p++) {
+ if (!(*p)->getAsTyped()->getAsConstantUnion())
+ return false;
+ }
+ }
+
+ return allConstant;
+}
+
+// This function is used to test for the correctness of the parameters passed to various constructor functions
+// and also convert them to the right datatype if it is allowed and required.
+//
+// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
+//
+TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line)
+{
+ if (node == 0)
+ return 0;
+
+ TIntermAggregate* aggrNode = node->getAsAggregate();
+
+ TTypeList::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 {
+ error(line, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount,
+ node->getAsTyped()->getType().getBasicString(), type->getBasicString());
+ recover();
+ }
+
+ return 0;
+}
+
+//
+// This function returns the tree representation for the vector field(s) being accessed from contant vector.
+// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
+// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
+// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of
+// a constant matrix.
+//
+TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line)
+{
+ TIntermTyped* typedNode;
+ TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+
+ ConstantUnion *unionArray;
+ if (tempConstantNode) {
+ unionArray = tempConstantNode->getUnionArrayPointer();
+
+ if (!unionArray) { // this error message should never be raised
+ infoSink.info.message(EPrefixInternalError, "ConstantUnion not initialized in addConstVectorNode function", line);
+ recover();
+
+ return node;
+ }
+ } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
+ error(line, "Cannot offset into the vector", "Error", "");
+ recover();
+
+ return 0;
+ }
+
+ ConstantUnion* constArray = new ConstantUnion[fields.num];
+
+ for (int i = 0; i < fields.num; i++) {
+ if (fields.offsets[i] >= node->getType().getObjectSize()) {
+ error(line, "", "[", "vector field selection out of range '%d'", fields.offsets[i]);
+ recover();
+ fields.offsets[i] = 0;
+ }
+
+ constArray[i] = unionArray[fields.offsets[i]];
+
+ }
+ typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
+ return typedNode;
+}
+
+//
+// This function returns the column being accessed from a constant matrix. The values are retrieved from
+// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input
+// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a
+// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
+//
+TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line)
+{
+ TIntermTyped* typedNode;
+ TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+
+ if (index >= node->getType().getNominalSize()) {
+ error(line, "", "[", "matrix field selection out of range '%d'", index);
+ recover();
+ index = 0;
+ }
+
+ if (tempConstantNode) {
+ 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()) {
+ error(line, "", "[", "array field selection out of range '%d'", index);
+ 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;
+}
+
+//
+// Initialize all supported extensions to disable
+//
+void TParseContext::initializeExtensionBehavior()
+{
+ //
+ // example code: extensionBehavior["test"] = EBhDisable; // where "test" is the name of
+ // supported extension
+ //
+ extensionBehavior["GL_ARB_texture_rectangle"] = EBhRequire;
+ extensionBehavior["GL_3DL_array_objects"] = EBhDisable;
+}
+
+OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
+
+bool InitializeParseContextIndex()
+{
+ if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) {
+ assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
+ return false;
+ }
+
+ //
+ // Allocate a TLS index.
+ //
+ GlobalParseContextIndex = OS_AllocTLSIndex();
+
+ if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
+ return false;
+ }
+
+ return true;
+}
+
+bool FreeParseContextIndex()
+{
+ OS_TLSIndex tlsiIndex = GlobalParseContextIndex;
+
+ if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "FreeParseContextIndex(): Parse Context index not initalised");
+ return false;
+ }
+
+ GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
+
+ return OS_FreeTLSIndex(tlsiIndex);
+}
+
+bool InitializeGlobalParseContext()
+{
+ if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalised");
+ return false;
+ }
+
+ TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+ if (lpParseContext != 0) {
+ assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
+ return false;
+ }
+
+ TThreadParseContext *lpThreadData = new TThreadParseContext();
+ if (lpThreadData == 0) {
+ assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context");
+ return false;
+ }
+
+ lpThreadData->lpGlobalParseContext = 0;
+ OS_SetTLSValue(GlobalParseContextIndex, lpThreadData);
+
+ return true;
+}
+
+bool FreeParseContext()
+{
+ if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "FreeParseContext(): Parse Context index not initalised");
+ return false;
+ }
+
+ TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+ if (lpParseContext)
+ delete lpParseContext;
+
+ return true;
+}
+
+TParseContextPointer& GetGlobalParseContext()
+{
+ //
+ // Minimal error checking for speed
+ //
+
+ TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+
+ return lpParseContext->lpGlobalParseContext;
+}
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/ParseHelper.h b/Source/ThirdParty/ANGLE/src/compiler/ParseHelper.h
new file mode 100644
index 0000000..792333f
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/ParseHelper.h
@@ -0,0 +1,123 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef _PARSER_HELPER_INCLUDED_
+#define _PARSER_HELPER_INCLUDED_
+
+#include "compiler/ShHandle.h"
+#include "compiler/SymbolTable.h"
+#include "compiler/localintermediate.h"
+
+struct TMatrixFields {
+ bool wholeRow;
+ bool wholeCol;
+ int row;
+ int col;
+};
+
+typedef enum {
+ EBhRequire,
+ EBhEnable,
+ EBhWarn,
+ EBhDisable
+} TBehavior;
+
+struct TPragma {
+ TPragma(bool o, bool d) : optimize(o), debug(d) { }
+ bool optimize;
+ bool debug;
+ TPragmaTable pragmaTable;
+};
+
+//
+// The following are extra variables needed during parsing, grouped together so
+// they can be passed to the parser without needing a global.
+//
+struct TParseContext {
+ TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage l, EShSpec s, TInfoSink& is) :
+ intermediate(interm), symbolTable(symt), infoSink(is), language(l), spec(s), treeRoot(0),
+ recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0),
+ inTypeParen(false), contextPragma(true, false) { }
+ TIntermediate& intermediate; // to hold and build a parse tree
+ TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed
+ TInfoSink& infoSink;
+ EShLanguage language; // vertex or fragment language (future: pack or unpack)
+ EShSpec spec; // The language specification compiler conforms to - GLES2 or WebGL.
+ TIntermNode* treeRoot; // root of parse tree being created
+ bool recoveredFromError; // true if a parse error has occurred, but we continue to parse
+ int numErrors;
+ bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier
+ int loopNestingLevel; // 0 if outside all loops
+ bool inTypeParen; // true if in parentheses, looking only for an identifier
+ const TType* currentFunctionType; // the return type of the function that's currently being parsed
+ bool functionReturnsValue; // true if a non-void function has a return
+ TMap<TString, TBehavior> extensionBehavior;
+ void initializeExtensionBehavior();
+
+ void error(TSourceLoc, const char *szReason, const char *szToken,
+ const char *szExtraInfoFormat, ...);
+ bool reservedErrorCheck(int line, const TString& identifier);
+ void recover();
+
+ bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line);
+ bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, int line);
+ void assignError(int line, const char* op, TString left, TString right);
+ void unaryOpError(int line, const char* op, TString operand);
+ void binaryOpError(int line, const char* op, TString left, TString right);
+ bool 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 containsSampler(TType& type);
+ bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type);
+ bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type);
+ bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
+ bool extensionErrorCheck(int line, const char*);
+ const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);
+ bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
+ TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
+ bool areAllChildConst(TIntermAggregate* aggrNode);
+ TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc);
+ TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type);
+ TIntermTyped* constructStruct(TIntermNode*, TType*, int, TSourceLoc, bool subset);
+ TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, TSourceLoc, bool subset);
+ TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc);
+ TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc);
+ TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line);
+ TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc);
+ bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
+ struct TPragma contextPragma;
+ TString HashErrMsg;
+ bool AfterEOF;
+};
+
+int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext&);
+void PaReservedWord();
+int PaIdentOrType(TString& id, TParseContext&, TSymbol*&);
+int PaParseComment(int &lineno, TParseContext&);
+void setInitialState();
+
+typedef TParseContext* TParseContextPointer;
+extern TParseContextPointer& GetGlobalParseContext();
+#define GlobalParseContext GetGlobalParseContext()
+
+typedef struct TThreadParseContextRec
+{
+ TParseContext *lpGlobalParseContext;
+} TThreadParseContext;
+
+#endif // _PARSER_HELPER_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.cpp b/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.cpp
new file mode 100644
index 0000000..7e348ca
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.cpp
@@ -0,0 +1,318 @@
+//
+// 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 "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;
+
+ TPoolAllocator *globalPoolAllocator = new TPoolAllocator(true);
+
+ TThreadGlobalPools* threadData = new TThreadGlobalPools();
+
+ threadData->globalPoolAllocator = globalPoolAllocator;
+
+ OS_SetTLSValue(PoolIndex, threadData);
+ globalPoolAllocator->push();
+}
+
+void FreeGlobalPools()
+{
+ // Release the allocated memory for this thread.
+ TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
+ if (!globalPools)
+ return;
+
+ GlobalPoolAllocator.popAll();
+ delete &GlobalPoolAllocator;
+ delete globalPools;
+}
+
+bool InitializePoolIndex()
+{
+ // Allocate a TLS index.
+ if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
+ return false;
+
+ return true;
+}
+
+void FreePoolIndex()
+{
+ // Release the TLS index.
+ OS_FreeTLSIndex(PoolIndex);
+}
+
+TPoolAllocator& GetGlobalPoolAllocator()
+{
+ TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
+
+ return *threadData->globalPoolAllocator;
+}
+
+void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator)
+{
+ TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
+
+ threadData->globalPoolAllocator = poolAllocator;
+}
+
+//
+// Implement the functionality of the TPoolAllocator class, which
+// is documented in PoolAlloc.h.
+//
+TPoolAllocator::TPoolAllocator(bool g, int growthIncrement, int allocationAlignment) :
+ global(g),
+ pageSize(growthIncrement),
+ alignment(allocationAlignment),
+ freeList(0),
+ inUseList(0),
+ numCalls(0)
+{
+ //
+ // Don't allow page sizes we know are smaller than all common
+ // OS page sizes.
+ //
+ if (pageSize < 4*1024)
+ pageSize = 4*1024;
+
+ //
+ // A large currentPageOffset indicates a new page needs to
+ // be obtained to allocate memory.
+ //
+ currentPageOffset = pageSize;
+
+ //
+ // Adjust alignment to be at least pointer aligned and
+ // power of 2.
+ //
+ size_t minAlign = sizeof(void*);
+ alignment &= ~(minAlign - 1);
+ if (alignment < minAlign)
+ alignment = minAlign;
+ size_t a = 1;
+ while (a < alignment)
+ a <<= 1;
+ alignment = a;
+ alignmentMask = a - 1;
+
+ //
+ // Align header skip
+ //
+ headerSkip = minAlign;
+ if (headerSkip < sizeof(tHeader)) {
+ headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
+ }
+}
+
+TPoolAllocator::~TPoolAllocator()
+{
+ if (!global) {
+ //
+ // Then we know that this object is not being
+ // allocated after other, globally scoped objects
+ // that depend on it. So we can delete the "in use" memory.
+ //
+ while (inUseList) {
+ tHeader* next = inUseList->nextPage;
+ inUseList->~tHeader();
+ delete [] reinterpret_cast<char*>(inUseList);
+ inUseList = next;
+ }
+ }
+
+ //
+ // Always delete the free list memory - it can't be being
+ // (correctly) referenced, whether the pool allocator was
+ // global or not. We should not check the guard blocks
+ // here, because we did it already when the block was
+ // placed into the free list.
+ //
+ while (freeList) {
+ tHeader* next = freeList->nextPage;
+ delete [] reinterpret_cast<char*>(freeList);
+ freeList = next;
+ }
+}
+
+// Support MSVC++ 6.0
+const unsigned char TAllocation::guardBlockBeginVal = 0xfb;
+const unsigned char TAllocation::guardBlockEndVal = 0xfe;
+const unsigned char TAllocation::userDataFill = 0xcd;
+
+#ifdef GUARD_BLOCKS
+ const size_t TAllocation::guardBlockSize = 16;
+#else
+ const size_t TAllocation::guardBlockSize = 0;
+#endif
+
+//
+// Check a single guard block for damage
+//
+void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const
+{
+ for (size_t x = 0; x < guardBlockSize; x++) {
+ if (blockMem[x] != val) {
+ char assertMsg[80];
+
+ // We don't print the assert message. It's here just to be helpful.
+ sprintf(assertMsg, "PoolAlloc: Damage %s %u byte allocation at 0x%p\n",
+ locText, size, data());
+ assert(0 && "PoolAlloc: Damage in guard block");
+ }
+ }
+}
+
+
+void TPoolAllocator::push()
+{
+ tAllocState state = { currentPageOffset, inUseList };
+
+ stack.push_back(state);
+
+ //
+ // Indicate there is no current page to allocate from.
+ //
+ currentPageOffset = pageSize;
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred since the last push(), or since the
+// last pop(), or since the object's creation.
+//
+// The deallocated pages are saved for future allocations.
+//
+void TPoolAllocator::pop()
+{
+ if (stack.size() < 1)
+ return;
+
+ tHeader* page = stack.back().page;
+ currentPageOffset = stack.back().offset;
+
+ while (inUseList != page) {
+ // invoke destructor to free allocation list
+ inUseList->~tHeader();
+
+ tHeader* nextInUse = inUseList->nextPage;
+ if (inUseList->pageCount > 1)
+ delete [] reinterpret_cast<char*>(inUseList);
+ else {
+ inUseList->nextPage = freeList;
+ freeList = inUseList;
+ }
+ inUseList = nextInUse;
+ }
+
+ stack.pop_back();
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred.
+//
+void TPoolAllocator::popAll()
+{
+ while (stack.size() > 0)
+ pop();
+}
+
+void* TPoolAllocator::allocate(size_t numBytes)
+{
+ // If we are using guard blocks, all allocations are bracketed by
+ // them: [guardblock][allocation][guardblock]. numBytes is how
+ // much memory the caller asked for. allocationSize is the total
+ // size including guard blocks. In release build,
+ // guardBlockSize=0 and this all gets optimized away.
+ size_t allocationSize = TAllocation::allocationSize(numBytes);
+
+ //
+ // Just keep some interesting statistics.
+ //
+ ++numCalls;
+ totalBytes += numBytes;
+
+ //
+ // Do the allocation, most likely case first, for efficiency.
+ // This step could be moved to be inline sometime.
+ //
+ if (currentPageOffset + allocationSize <= pageSize) {
+ //
+ // Safe to allocate from currentPageOffset.
+ //
+ unsigned char* memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset;
+ currentPageOffset += allocationSize;
+ currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;
+
+ return initializeAllocation(inUseList, memory, numBytes);
+ }
+
+ if (allocationSize + headerSkip > pageSize) {
+ //
+ // Do a multi-page allocation. Don't mix these with the others.
+ // The OS is efficient and allocating and free-ing multiple pages.
+ //
+ size_t numBytesToAlloc = allocationSize + headerSkip;
+ tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
+ if (memory == 0)
+ return 0;
+
+ // Use placement-new to initialize header
+ new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
+ inUseList = memory;
+
+ currentPageOffset = pageSize; // make next allocation come from a new page
+
+ // No guard blocks for multi-page allocations (yet)
+ return reinterpret_cast<void*>(reinterpret_cast<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/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.h b/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.h
new file mode 100644
index 0000000..645db78
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.h
@@ -0,0 +1,304 @@
+//
+// 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(bool global = false, int growthIncrement = 8*1024, int allocationAlignment = 16);
+
+ //
+ // Don't call the destructor just to free up the memory, call pop()
+ //
+ ~TPoolAllocator();
+
+ //
+ // Call push() to establish a new place to pop memory too. Does not
+ // have to be called to get things started.
+ //
+ void push();
+
+ //
+ // Call pop() to free all memory allocated since the last call to push(),
+ // or if no last call to push, frees all memory since first allocation.
+ //
+ void pop();
+
+ //
+ // Call popAll() to free all memory allocated.
+ //
+ void popAll();
+
+ //
+ // Call allocate() to actually acquire memory. Returns 0 if no memory
+ // available, otherwise a properly aligned pointer to 'numBytes' of memory.
+ //
+ void* allocate(size_t numBytes);
+
+ //
+ // There is no deallocate. The point of this class is that
+ // deallocation can be skipped by the user of it, as the model
+ // of use is to simultaneously deallocate everything at once
+ // by calling pop(), and to not have to solve memory leak problems.
+ //
+
+protected:
+ friend struct tHeader;
+
+ struct tHeader {
+ tHeader(tHeader* nextPage, size_t pageCount) :
+ 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);
+ }
+
+ bool global; // should be true if this object is globally scoped
+ size_t pageSize; // granularity of allocation from the OS
+ size_t alignment; // all returned allocations will be aligned at
+ // this granularity, which will be a power of 2
+ size_t alignmentMask;
+ size_t headerSkip; // amount of memory to skip to make room for the
+ // header (basically, size of header, rounded
+ // up to make it aligned
+ size_t currentPageOffset; // next offset in top of inUseList to allocate from
+ tHeader* freeList; // list of popped memory
+ tHeader* inUseList; // list of all memory currently being used
+ tAllocStack stack; // stack of where to allocate from, to partition pool
+
+ int numCalls; // just an interesting statistic
+ size_t totalBytes; // just an interesting statistic
+private:
+ TPoolAllocator& operator=(const TPoolAllocator&); // dont allow assignment operator
+ TPoolAllocator(const TPoolAllocator&); // dont allow default copy constructor
+};
+
+
+//
+// There could potentially be many pools with pops happening at
+// different times. But a simple use is to have a global pop
+// with everyone using the same global allocator.
+//
+typedef TPoolAllocator* PoolAllocatorPointer;
+extern TPoolAllocator& GetGlobalPoolAllocator();
+#define GlobalPoolAllocator GetGlobalPoolAllocator()
+
+
+struct TThreadGlobalPools
+{
+ TPoolAllocator* globalPoolAllocator;
+};
+
+void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator);
+
+//
+// This STL compatible allocator is intended to be used as the allocator
+// parameter to templatized STL containers, like vector and map.
+//
+// It will use the pools for allocation, and not
+// do any deallocation, but will still do destruction.
+//
+template<class T>
+class pool_allocator {
+public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T value_type;
+
+ template<class Other>
+ struct rebind {
+ typedef pool_allocator<Other> other;
+ };
+ pointer address(reference x) const { return &x; }
+ const_pointer address(const_reference x) const { return &x; }
+
+ 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(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/Source/ThirdParty/ANGLE/src/compiler/QualifierAlive.cpp b/Source/ThirdParty/ANGLE/src/compiler/QualifierAlive.cpp
new file mode 100644
index 0000000..92a6874
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/QualifierAlive.cpp
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/intermediate.h"
+
+class TAliveTraverser : public TIntermTraverser {
+public:
+ TAliveTraverser(TQualifier q) : TIntermTraverser(true, false, false, true), found(false), qualifier(q)
+ {
+ }
+
+ bool wasFound() { return found; }
+
+protected:
+ bool found;
+ TQualifier qualifier;
+
+ void visitSymbol(TIntermSymbol*);
+ bool visitSelection(Visit, TIntermSelection*);
+};
+
+//
+// Report whether or not a variable of the given qualifier type
+// is guaranteed written. Not always possible to determine if
+// it is written conditionally.
+//
+// ?? It does not do this well yet, this is just a place holder
+// that simply determines if it was reference at all, anywhere.
+//
+bool QualifierWritten(TIntermNode* node, TQualifier qualifier)
+{
+ TAliveTraverser it(qualifier);
+
+ if (node)
+ node->traverse(&it);
+
+ return it.wasFound();
+}
+
+void TAliveTraverser::visitSymbol(TIntermSymbol* node)
+{
+ //
+ // If it's what we're looking for, record it.
+ //
+ if (node->getQualifier() == qualifier)
+ found = true;
+}
+
+bool TAliveTraverser::visitSelection(Visit preVisit, TIntermSelection* node)
+{
+ if (wasFound())
+ return false;
+
+ return true;
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/QualifierAlive.h b/Source/ThirdParty/ANGLE/src/compiler/QualifierAlive.h
new file mode 100644
index 0000000..872a06f
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/QualifierAlive.h
@@ -0,0 +1,7 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+bool QualifierWritten(TIntermNode* root, TQualifier);
diff --git a/Source/ThirdParty/ANGLE/src/compiler/RemoveTree.cpp b/Source/ThirdParty/ANGLE/src/compiler/RemoveTree.cpp
new file mode 100644
index 0000000..a4b8c1e
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/RemoveTree.cpp
@@ -0,0 +1,77 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/intermediate.h"
+#include "compiler/RemoveTree.h"
+
+//
+// Code to recursively delete the intermediate tree.
+//
+
+class RemoveTree : public TIntermTraverser
+{
+public:
+ RemoveTree() : TIntermTraverser(false, false, true)
+ {
+ }
+
+protected:
+ void visitSymbol(TIntermSymbol*);
+ void visitConstantUnion(TIntermConstantUnion*);
+ bool visitBinary(Visit visit, TIntermBinary*);
+ bool visitUnary(Visit visit, TIntermUnary*);
+ bool visitSelection(Visit visit, TIntermSelection*);
+ bool visitAggregate(Visit visit, TIntermAggregate*);
+};
+
+void RemoveTree::visitSymbol(TIntermSymbol* node)
+{
+ delete node;
+}
+
+bool RemoveTree::visitBinary(Visit visit, TIntermBinary* node)
+{
+ delete node;
+
+ return true;
+}
+
+bool RemoveTree::visitUnary(Visit visit, TIntermUnary* node)
+{
+ delete node;
+
+ return true;
+}
+
+bool RemoveTree::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+ delete node;
+
+ return true;
+}
+
+bool RemoveTree::visitSelection(Visit visit, TIntermSelection* node)
+{
+ delete node;
+
+ return true;
+}
+
+void RemoveTree::visitConstantUnion(TIntermConstantUnion* node)
+{
+ delete node;
+}
+
+//
+// Entry point.
+//
+void RemoveAllTreeNodes(TIntermNode* root)
+{
+ RemoveTree it;
+
+ root->traverse(&it);
+}
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/RemoveTree.h b/Source/ThirdParty/ANGLE/src/compiler/RemoveTree.h
new file mode 100644
index 0000000..97a8216
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/RemoveTree.h
@@ -0,0 +1,7 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+void RemoveAllTreeNodes(TIntermNode*);
diff --git a/Source/ThirdParty/ANGLE/src/compiler/ShHandle.h b/Source/ThirdParty/ANGLE/src/compiler/ShHandle.h
new file mode 100644
index 0000000..5ef5d30
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/ShHandle.h
@@ -0,0 +1,76 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#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/InfoSink.h"
+#include "compiler/SymbolTable.h"
+
+class TCompiler;
+class TIntermNode;
+
+//
+// The base class used to back handles returned to the driver.
+//
+class TShHandleBase {
+public:
+ TShHandleBase() { }
+ virtual ~TShHandleBase() { }
+ virtual TCompiler* getAsCompiler() { return 0; }
+};
+
+//
+// The base class for the machine dependent compiler to derive from
+// for managing object code from the compile.
+//
+class TCompiler : public TShHandleBase {
+public:
+ TCompiler(EShLanguage l, EShSpec s) : language(l), spec(s) { }
+ virtual ~TCompiler() { }
+
+ EShLanguage getLanguage() const { return language; }
+ EShSpec getSpec() const { return spec; }
+ TSymbolTable& getSymbolTable() { return symbolTable; }
+ TInfoSink& getInfoSink() { return infoSink; }
+
+ virtual bool compile(TIntermNode* root) = 0;
+
+ virtual TCompiler* getAsCompiler() { return this; }
+
+protected:
+ EShLanguage language;
+ EShSpec spec;
+
+ // Built-in symbol table for the given language, spec, and resources.
+ // It is preserved from compile-to-compile.
+ TSymbolTable symbolTable;
+ // Output sink.
+ TInfoSink infoSink;
+};
+
+//
+// This is the interface between the machine independent code
+// and the machine dependent code.
+//
+// The machine dependent code should derive from the classes
+// above. Then Construct*() and Delete*() will create and
+// destroy the machine dependent objects, which contain the
+// above machine independent information.
+//
+TCompiler* ConstructCompiler(EShLanguage, EShSpec);
+void DeleteCompiler(TCompiler*);
+
+#endif // _SHHANDLE_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/ShaderLang.cpp b/Source/ThirdParty/ANGLE/src/compiler/ShaderLang.cpp
new file mode 100644
index 0000000..e0c646a
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/ShaderLang.cpp
@@ -0,0 +1,311 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Implement the top-level of interface to the compiler,
+// as defined in ShaderLang.h
+//
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/Initialize.h"
+#include "compiler/InitializeDll.h"
+#include "compiler/ParseHelper.h"
+#include "compiler/ShHandle.h"
+#include "compiler/SymbolTable.h"
+
+static bool InitializeSymbolTable(
+ const TBuiltInStrings& builtInStrings,
+ EShLanguage language, EShSpec spec, const TBuiltInResource& resources,
+ TInfoSink& infoSink, TSymbolTable& symbolTable)
+{
+ TIntermediate intermediate(infoSink);
+ TParseContext parseContext(symbolTable, intermediate, language, spec, infoSink);
+
+ GlobalParseContext = &parseContext;
+
+ setInitialState();
+
+ 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();
+
+ //Initialize the Preprocessor
+ if (InitPreprocessor())
+ {
+ infoSink.info.message(EPrefixInternalError, "Unable to intialize the Preprocessor");
+ return false;
+ }
+
+ for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
+ {
+ const char* builtInShaders[1];
+ int builtInLengths[1];
+
+ builtInShaders[0] = (*i).c_str();
+ builtInLengths[0] = (int) (*i).size();
+
+ if (PaParseStrings(const_cast<char**>(builtInShaders), builtInLengths, 1, parseContext) != 0)
+ {
+ infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
+ return false;
+ }
+ }
+
+ IdentifyBuiltIns(language, spec, resources, symbolTable);
+
+ FinalizePreprocessor();
+
+ return true;
+}
+
+static bool GenerateBuiltInSymbolTable(
+ EShLanguage language, EShSpec spec, const TBuiltInResource& resources,
+ TInfoSink& infoSink, TSymbolTable& symbolTable)
+{
+ TBuiltIns builtIns;
+
+ builtIns.initialize(language, spec, resources);
+ return InitializeSymbolTable(builtIns.getBuiltInStrings(), language, spec, resources, infoSink, symbolTable);
+}
+
+//
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler.
+//
+
+//
+// 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 ShInitBuiltInResource(TBuiltInResource* resources)
+{
+ // Constants.
+ resources->MaxVertexAttribs = 8;
+ resources->MaxVertexUniformVectors = 128;
+ resources->MaxVaryingVectors = 8;
+ resources->MaxVertexTextureImageUnits = 0;
+ resources->MaxCombinedTextureImageUnits = 8;
+ resources->MaxTextureImageUnits = 8;
+ resources->MaxFragmentUniformVectors = 16;
+ resources->MaxDrawBuffers = 1;
+
+ // Extensions.
+ resources->OES_standard_derivatives = 0;
+}
+
+//
+// Driver calls these to create and destroy compiler objects.
+//
+ShHandle ShConstructCompiler(EShLanguage language, EShSpec spec, const TBuiltInResource* resources)
+{
+ if (!InitThread())
+ return 0;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(language, spec));
+ TCompiler* compiler = base->getAsCompiler();
+ if (compiler == 0)
+ return 0;
+
+ // Generate built-in symbol table.
+ if (!GenerateBuiltInSymbolTable(language, spec, *resources, compiler->getInfoSink(), compiler->getSymbolTable())) {
+ 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,
+ const EShOptimizationLevel optLevel,
+ int debugOptions
+ )
+{
+ if (!InitThread())
+ return 0;
+
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+ TCompiler* compiler = base->getAsCompiler();
+ if (compiler == 0)
+ return 0;
+
+ GlobalPoolAllocator.push();
+ TInfoSink& infoSink = compiler->getInfoSink();
+ infoSink.info.erase();
+ infoSink.debug.erase();
+ infoSink.obj.erase();
+
+ if (numStrings == 0)
+ return 1;
+
+ TIntermediate intermediate(infoSink);
+ TSymbolTable& symbolTable = compiler->getSymbolTable();
+
+ TParseContext parseContext(symbolTable, intermediate, compiler->getLanguage(), compiler->getSpec(), infoSink);
+ parseContext.initializeExtensionBehavior();
+ GlobalParseContext = &parseContext;
+
+ setInitialState();
+
+ InitPreprocessor();
+ //
+ // Parse the application's shaders. All the following symbol table
+ // work will be throw-away, so push a new allocation scope that can
+ // be thrown away, then push a scope for the current shader's globals.
+ //
+ bool success = true;
+
+ symbolTable.push();
+ if (!symbolTable.atGlobalLevel())
+ parseContext.infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
+
+ int ret = PaParseStrings(const_cast<char**>(shaderStrings), 0, numStrings, parseContext);
+ if (ret)
+ success = false;
+
+ if (success && parseContext.treeRoot) {
+ if (optLevel == EShOptNoGeneration)
+ parseContext.infoSink.info.message(EPrefixNone, "No errors. No code generation was requested.");
+ else {
+ success = intermediate.postProcess(parseContext.treeRoot, parseContext.language);
+
+ if (success) {
+
+ if (debugOptions & EDebugOpIntermediate)
+ intermediate.outputTree(parseContext.treeRoot);
+
+ //
+ // Call the machine dependent compiler
+ //
+ if (!compiler->compile(parseContext.treeRoot))
+ success = false;
+ }
+ }
+ } else if (!success) {
+ parseContext.infoSink.info.prefix(EPrefixError);
+ parseContext.infoSink.info << parseContext.numErrors << " compilation errors. No code generated.\n\n";
+ success = false;
+ if (debugOptions & EDebugOpIntermediate)
+ intermediate.outputTree(parseContext.treeRoot);
+ } else if (!parseContext.treeRoot) {
+ parseContext.error(1, "Unexpected end of file.", "", "");
+ parseContext.infoSink.info << parseContext.numErrors << " compilation errors. No code generated.\n\n";
+ success = false;
+ if (debugOptions & EDebugOpIntermediate)
+ intermediate.outputTree(parseContext.treeRoot);
+ }
+
+ intermediate.remove(parseContext.treeRoot);
+
+ //
+ // Ensure symbol table is returned to the built-in level,
+ // throwing away all but the built-ins.
+ //
+ while (!symbolTable.atBuiltInLevel())
+ symbolTable.pop();
+
+ FinalizePreprocessor();
+ //
+ // Throw away all the temporary memory used by the compilation process.
+ //
+ GlobalPoolAllocator.pop();
+
+ return success ? 1 : 0;
+}
+
+//
+// Return any compiler log of messages for the application.
+//
+const char* ShGetInfoLog(const ShHandle handle)
+{
+ if (!InitThread())
+ return 0;
+
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+ TInfoSink* infoSink = 0;
+
+ if (base->getAsCompiler())
+ infoSink = &(base->getAsCompiler()->getInfoSink());
+
+ infoSink->info << infoSink->debug.c_str();
+ return infoSink->info.c_str();
+}
+
+//
+// Return any object code.
+//
+const char* ShGetObjectCode(const ShHandle handle)
+{
+ if (!InitThread())
+ return 0;
+
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+ TInfoSink* infoSink;
+
+ if (base->getAsCompiler())
+ infoSink = &(base->getAsCompiler()->getInfoSink());
+
+ return infoSink->obj.c_str();
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.cpp b/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.cpp
new file mode 100644
index 0000000..1b08667
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.cpp
@@ -0,0 +1,216 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Symbol table for parsing. Most functionaliy and main ideas
+// are documented in the header file.
+//
+
+#include "compiler/SymbolTable.h"
+
+#include <stdio.h>
+
+//
+// TType helper function needs a place to live.
+//
+
+//
+// Recursively generate mangled names.
+//
+void TType::buildMangledName(TString& mangledName)
+{
+ if (isMatrix())
+ mangledName += 'm';
+ else if (isVector())
+ mangledName += 'v';
+
+ switch (type) {
+ case EbtFloat: mangledName += 'f'; break;
+ case EbtInt: mangledName += 'i'; break;
+ case EbtBool: mangledName += 'b'; break;
+ case EbtSampler2D: mangledName += "s2"; break;
+ case EbtSamplerCube: mangledName += "sC"; break;
+ case EbtStruct:
+ mangledName += "struct-";
+ if (typeName)
+ mangledName += *typeName;
+ {// support MSVC++6.0
+ for (unsigned int i = 0; i < structure->size(); ++i) {
+ mangledName += '-';
+ (*structure)[i].type->buildMangledName(mangledName);
+ }
+ }
+ default:
+ break;
+ }
+
+ mangledName += static_cast<char>('0' + getNominalSize());
+ if (isArray()) {
+ char buf[20];
+ sprintf(buf, "%d", arraySize);
+ mangledName += '[';
+ mangledName += buf;
+ mangledName += ']';
+ }
+}
+
+int TType::getStructSize() const
+{
+ if (!getStruct()) {
+ assert(false && "Not a struct");
+ return 0;
+ }
+
+ if (structureSize == 0)
+ for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
+ structureSize += ((*tl).type)->getObjectSize();
+
+ return structureSize;
+}
+
+//
+// Dump functions.
+//
+
+void TVariable::dump(TInfoSink& infoSink) const
+{
+ infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.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);
+ }
+ }
+}
+
+
+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/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.h b/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.h
new file mode 100644
index 0000000..b1a80b5
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.h
@@ -0,0 +1,331 @@
+//
+// 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)
+ {
+ 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 setDefined() { defined = true; }
+ bool isDefined() { return defined; }
+
+ int getParamCount() const { return static_cast<int>(parameters.size()); }
+ TParameter& operator [](int i) { return parameters[i]; }
+ const TParameter& operator [](int i) const { return parameters[i]; }
+
+ virtual void dump(TInfoSink &infoSink) const;
+ TFunction(const TFunction&, TStructureMap& remapper);
+ virtual TFunction* clone(TStructureMap& remapper);
+
+protected:
+ typedef TVector<TParameter> TParamList;
+ TParamList parameters;
+ TType returnType;
+ TString mangledName;
+ TOperator op;
+ bool defined;
+};
+
+
+class TSymbolTableLevel {
+public:
+ typedef 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 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;
+ }
+
+ TSymbolTableLevel* getGlobalLevel() { assert(table.size() >= 2); return table[1]; }
+ void relateToOperator(const char* name, TOperator op) { table[0]->relateToOperator(name, op); }
+ int getMaxSymbolId() { return uniqueId; }
+ void dump(TInfoSink &infoSink) const;
+ void copyTable(const TSymbolTable& copyOf);
+
+ 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/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.cpp
new file mode 100644
index 0000000..7b8d903
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.cpp
@@ -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.
+//
+
+#include "compiler/TranslatorGLSL.h"
+
+#include "compiler/OutputGLSL.h"
+
+TranslatorGLSL::TranslatorGLSL(EShLanguage lang, EShSpec spec)
+ : TCompiler(lang, spec) {
+}
+
+bool TranslatorGLSL::compile(TIntermNode* root) {
+ TOutputGLSL outputGLSL(infoSink.obj);
+ root->traverse(&outputGLSL);
+
+ return true;
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.h b/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.h
new file mode 100644
index 0000000..973e39a
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.h
@@ -0,0 +1,18 @@
+//
+// 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(EShLanguage lang, EShSpec spec);
+ virtual bool compile(TIntermNode* root);
+};
+
+#endif // COMPILER_TRANSLATORGLSL_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.cpp
new file mode 100644
index 0000000..3a1e52d
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.cpp
@@ -0,0 +1,24 @@
+//
+// 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/OutputHLSL.h"
+
+TranslatorHLSL::TranslatorHLSL(EShLanguage lang, EShSpec spec)
+ : TCompiler(lang, spec)
+{
+}
+
+bool TranslatorHLSL::compile(TIntermNode *root)
+{
+ TParseContext& parseContext = *GetGlobalParseContext();
+ sh::OutputHLSL outputHLSL(parseContext);
+
+ outputHLSL.output();
+
+ return true;
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.h b/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.h
new file mode 100644
index 0000000..38a5f0c
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.h
@@ -0,0 +1,18 @@
+//
+// 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(EShLanguage lang, EShSpec spec);
+ virtual bool compile(TIntermNode* root);
+};
+
+#endif // COMPILER_TRANSLATORHLSL_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/Types.h b/Source/ThirdParty/ANGLE/src/compiler/Types.h
new file mode 100644
index 0000000..897b28f
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/Types.h
@@ -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.
+//
+
+#ifndef _TYPES_INCLUDED
+#define _TYPES_INCLUDED
+
+#include "compiler/BaseTypes.h"
+#include "compiler/Common.h"
+#include "compiler/debug.h"
+
+//
+// Need to have association of line numbers to types in a list for building structs.
+//
+class TType;
+struct TTypeLine {
+ TType* type;
+ int line;
+};
+typedef TVector<TTypeLine> TTypeList;
+
+inline TTypeList* NewPoolTTypeList()
+{
+ void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList));
+ return new(memory) TTypeList;
+}
+
+//
+// This is a workaround for a problem with the yacc stack, It can't have
+// types that it thinks have non-trivial constructors. It should
+// just be used while recognizing the grammar, not anything else. Pointers
+// could be used, but also trying to avoid lots of memory management overhead.
+//
+// Not as bad as it looks, there is no actual assumption that the fields
+// match up or are name the same or anything like that.
+//
+class TPublicType {
+public:
+ TBasicType type;
+ TQualifier qualifier;
+ TPrecision precision;
+ int size; // size of vector or matrix, not size of array
+ bool matrix;
+ bool array;
+ int arraySize;
+ TType* userDef;
+ int line;
+
+ void setBasic(TBasicType bt, TQualifier q, int ln = 0)
+ {
+ type = bt;
+ qualifier = q;
+ precision = 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;
+ }
+};
+
+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),
+ structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0)
+ {
+ }
+ explicit TType(const TPublicType &p) :
+ type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize),
+ structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0)
+ {
+ if (p.userDef) {
+ structure = p.userDef->getStruct();
+ typeName = NewPoolTString(p.userDef->getTypeName().c_str());
+ }
+ }
+ TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) :
+ type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
+ structure(userDef), structureSize(0), maxArraySize(0), arrayInformationType(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;
+ 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; }
+
+ 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;
+
+protected:
+ void buildMangledName(TString&);
+ int getStructSize() const;
+
+ TBasicType type : 6;
+ TPrecision precision;
+ TQualifier qualifier : 7;
+ int size : 8; // size of vector or matrix, not size of array
+ unsigned int matrix : 1;
+ unsigned int array : 1;
+ int arraySize;
+ int maxArraySize;
+ TType* arrayInformationType;
+
+ TTypeList* structure; // 0 unless this is a struct
+ mutable int structureSize;
+
+ TString *fieldName; // for structure field names
+ TString *mangled;
+ TString *typeName; // for structure field type name
+};
+
+#endif // _TYPES_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.cpp b/Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.cpp
new file mode 100644
index 0000000..20035fe
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.cpp
@@ -0,0 +1,63 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/UnfoldSelect.h"
+
+#include "compiler/InfoSink.h"
+#include "compiler/OutputHLSL.h"
+
+namespace sh
+{
+UnfoldSelect::UnfoldSelect(TParseContext &context, OutputHLSL *outputHLSL) : mContext(context), mOutputHLSL(outputHLSL)
+{
+ mTemporaryIndex = 0;
+}
+
+void UnfoldSelect::traverse(TIntermNode *node)
+{
+ mTemporaryIndex++;
+ node->traverse(this);
+}
+
+bool UnfoldSelect::visitSelection(Visit visit, TIntermSelection *node)
+{
+ TInfoSinkBase &out = mOutputHLSL->getBodyStream();
+
+ if (node->usesTernaryOperator())
+ {
+ int i = mTemporaryIndex++;
+
+ out << mOutputHLSL->typeString(node->getType()) << " t" << i << ";\n";
+
+ node->getCondition()->traverse(this);
+ out << "if(";
+ node->getCondition()->traverse(mOutputHLSL);
+ out << ")\n"
+ "{\n";
+ node->getTrueBlock()->traverse(this);
+ out << " t" << i << " = ";
+ node->getTrueBlock()->traverse(mOutputHLSL);
+ out << ";\n"
+ "}\n"
+ "else\n"
+ "{\n";
+ node->getCondition()->traverse(this);
+ out << " t" << i << " = ";
+ node->getFalseBlock()->traverse(mOutputHLSL);
+ out << ";\n"
+ "}\n";
+
+ mTemporaryIndex--;
+ }
+
+ return false;
+}
+
+int UnfoldSelect::getTemporaryIndex()
+{
+ return mTemporaryIndex;
+}
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.h b/Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.h
new file mode 100644
index 0000000..68b2e8a
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.h
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_UNFOLDSELECT_H_
+#define COMPILER_UNFOLDSELECT_H_
+
+#include "compiler/intermediate.h"
+#include "compiler/ParseHelper.h"
+
+namespace sh
+{
+class OutputHLSL;
+
+class UnfoldSelect : public TIntermTraverser
+{
+ public:
+ UnfoldSelect(TParseContext &context, OutputHLSL *outputHLSL);
+
+ void traverse(TIntermNode *node);
+ bool visitSelection(Visit visit, TIntermSelection *node);
+
+ int getTemporaryIndex();
+
+ protected:
+ TParseContext &mContext;
+ OutputHLSL *const mOutputHLSL;
+
+ int mTemporaryIndex;
+};
+}
+
+#endif // COMPILER_UNFOLDSELECT_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/debug.cpp b/Source/ThirdParty/ANGLE/src/compiler/debug.cpp
new file mode 100644
index 0000000..9642e1e
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/debug.cpp
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// debug.cpp: Debugging utilities.
+
+#include "compiler/debug.h"
+
+#include <stdarg.h>
+#include <stdio.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->infoSink.debug << buf;
+ }
+}
+} // extern "C"
+#endif // TRACE_ENABLED
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/debug.h b/Source/ThirdParty/ANGLE/src/compiler/debug.h
new file mode 100644
index 0000000..7a37151
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/debug.h
@@ -0,0 +1,53 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// debug.h: Debugging utilities.
+
+#ifndef COMPILER_DEBUG_H_
+#define COMPILER_DEBUG_H_
+
+#include <assert.h>
+
+#ifdef _DEBUG
+#define TRACE_ENABLED // define to enable debug message tracing
+#endif // _DEBUG
+
+// Outputs text to the debug log
+#ifdef TRACE_ENABLED
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+void Trace(const char* format, ...);
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#else // TRACE_ENABLED
+
+#define Trace(...) ((void)0)
+
+#endif // TRACE_ENABLED
+
+// A macro asserting a condition and outputting failures to the debug log
+#define ASSERT(expression) do { \
+ if(!(expression)) \
+ Trace("Assert failed: %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \
+ assert(expression); \
+} while(0)
+
+#define UNIMPLEMENTED() do { \
+ Trace("Unimplemented invoked: %s(%d)\n", __FUNCTION__, __LINE__); \
+ assert(false); \
+} while(0)
+
+#define UNREACHABLE() do { \
+ Trace("Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \
+ assert(false); \
+} while(0)
+
+#endif // COMPILER_DEBUG_H_
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/glslang.l b/Source/ThirdParty/ANGLE/src/compiler/glslang.l
new file mode 100644
index 0000000..02c226f
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/glslang.l
@@ -0,0 +1,600 @@
+/*
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+*/
+/* Based on
+ANSI C grammar, Lex specification
+
+In 1985, Jeff Lee published this Lex specification together with a Yacc
+grammar for the April 30, 1985 ANSI C draft. Tom Stockfisch reposted
+both to net.sources in 1987; that original, as mentioned in the answer
+to question 17.25 of the comp.lang.c FAQ, can be ftp'ed from ftp.uu.net,
+file usenet/net.sources/ansi.c.grammar.Z.
+
+I intend to keep this version as close to the current C Standard grammar
+as possible; please let me know if you discover discrepancies.
+
+Jutta Degener, 1995
+*/
+
+D [0-9]
+L [a-zA-Z_]
+H [a-fA-F0-9]
+E [Ee][+-]?{D}+
+O [0-7]
+
+%option nounput
+%{
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "compiler/ParseHelper.h"
+#include "glslang_tab.h"
+
+/* windows only pragma */
+#ifdef _MSC_VER
+#pragma warning(disable : 4102)
+#endif
+
+int yy_input(char* buf, int max_size);
+
+extern int yyparse(void*);
+#define YY_DECL int yylex(YYSTYPE* pyylval, void* parseContextLocal)
+#define parseContext (*((TParseContext*)(parseContextLocal)))
+
+#define YY_INPUT(buf,result,max_size) (result = yy_input(buf, max_size))
+
+%}
+
+/*
+TODO(alokp): yylineno is only here to support old flex.exe in compiler/tools.
+Remove it when we can exclusively use the newer version.
+*/
+%option yylineno
+
+%option noyywrap
+%option never-interactive
+%x FIELDS
+
+
+%%
+<*>"//"[^\n]*"\n" { /* ?? carriage and/or line-feed? */ };
+
+"invariant" { pyylval->lex.line = yylineno; return(INVARIANT); }
+"highp" { pyylval->lex.line = yylineno; return(HIGH_PRECISION); }
+"mediump" { pyylval->lex.line = yylineno; return(MEDIUM_PRECISION); }
+"lowp" { pyylval->lex.line = yylineno; return(LOW_PRECISION); }
+"precision" { pyylval->lex.line = yylineno; return(PRECISION); }
+
+"attribute" { pyylval->lex.line = yylineno; return(ATTRIBUTE); }
+"const" { pyylval->lex.line = yylineno; return(CONST_QUAL); }
+"uniform" { pyylval->lex.line = yylineno; return(UNIFORM); }
+"varying" { pyylval->lex.line = yylineno; return(VARYING); }
+
+"break" { pyylval->lex.line = yylineno; return(BREAK); }
+"continue" { pyylval->lex.line = yylineno; return(CONTINUE); }
+"do" { pyylval->lex.line = yylineno; return(DO); }
+"for" { pyylval->lex.line = yylineno; return(FOR); }
+"while" { pyylval->lex.line = yylineno; return(WHILE); }
+
+"if" { pyylval->lex.line = yylineno; return(IF); }
+"else" { pyylval->lex.line = yylineno; return(ELSE); }
+
+"in" { pyylval->lex.line = yylineno; return(IN_QUAL); }
+"out" { pyylval->lex.line = yylineno; return(OUT_QUAL); }
+"inout" { pyylval->lex.line = yylineno; return(INOUT_QUAL); }
+
+"float" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(FLOAT_TYPE); }
+"int" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(INT_TYPE); }
+"void" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(VOID_TYPE); }
+"bool" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(BOOL_TYPE); }
+"true" { pyylval->lex.line = yylineno; pyylval->lex.b = true; return(BOOLCONSTANT); }
+"false" { pyylval->lex.line = yylineno; pyylval->lex.b = false; return(BOOLCONSTANT); }
+
+"discard" { pyylval->lex.line = yylineno; return(DISCARD); }
+"return" { pyylval->lex.line = yylineno; return(RETURN); }
+
+"mat2" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX2); }
+"mat3" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX3); }
+"mat4" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX4); }
+
+"vec2" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC2); }
+"vec3" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC3); }
+"vec4" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC4); }
+"ivec2" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC2); }
+"ivec3" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC3); }
+"ivec4" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC4); }
+"bvec2" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC2); }
+"bvec3" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC3); }
+"bvec4" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC4); }
+
+"sampler2D" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER2D; }
+"samplerCube" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLERCUBE; }
+
+"struct" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(STRUCT); }
+
+"asm" { PaReservedWord(); return 0; }
+
+"class" { PaReservedWord(); return 0; }
+"union" { PaReservedWord(); return 0; }
+"enum" { PaReservedWord(); return 0; }
+"typedef" { PaReservedWord(); return 0; }
+"template" { PaReservedWord(); return 0; }
+"this" { PaReservedWord(); return 0; }
+"packed" { PaReservedWord(); return 0; }
+
+"goto" { PaReservedWord(); return 0; }
+"switch" { PaReservedWord(); return 0; }
+"default" { PaReservedWord(); return 0; }
+
+"inline" { PaReservedWord(); return 0; }
+"noinline" { PaReservedWord(); return 0; }
+"volatile" { PaReservedWord(); return 0; }
+"public" { PaReservedWord(); return 0; }
+"static" { PaReservedWord(); return 0; }
+"extern" { PaReservedWord(); return 0; }
+"external" { PaReservedWord(); return 0; }
+"interface" { PaReservedWord(); return 0; }
+
+"long" { PaReservedWord(); return 0; }
+"short" { PaReservedWord(); return 0; }
+"double" { PaReservedWord(); return 0; }
+"half" { PaReservedWord(); return 0; }
+"fixed" { PaReservedWord(); return 0; }
+"unsigned" { PaReservedWord(); return 0; }
+
+"input" { PaReservedWord(); return 0; }
+"output" { PaReservedWord(); return 0; }
+
+"hvec2" { PaReservedWord(); return 0; }
+"hvec3" { PaReservedWord(); return 0; }
+"hvec4" { PaReservedWord(); return 0; }
+"fvec2" { PaReservedWord(); return 0; }
+"fvec3" { PaReservedWord(); return 0; }
+"fvec4" { PaReservedWord(); return 0; }
+"dvec2" { PaReservedWord(); return 0; }
+"dvec3" { PaReservedWord(); return 0; }
+"dvec4" { PaReservedWord(); return 0; }
+
+"sizeof" { PaReservedWord(); return 0; }
+"cast" { PaReservedWord(); return 0; }
+
+"namespace" { PaReservedWord(); return 0; }
+"using" { PaReservedWord(); return 0; }
+
+{L}({L}|{D})* {
+ pyylval->lex.line = yylineno;
+ pyylval->lex.string = NewPoolTString(yytext);
+ return PaIdentOrType(*pyylval->lex.string, parseContext, pyylval->lex.symbol);
+}
+
+0[xX]{H}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+0{O}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+0{D}+ { pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); parseContext.recover(); return 0;}
+{D}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+
+{D}+{E} { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
+{D}+"."{D}*({E})? { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
+"."{D}+({E})? { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
+
+"/*" { int ret = PaParseComment(pyylval->lex.line, parseContext); if (!ret) return ret; }
+
+"+=" { pyylval->lex.line = yylineno; return(ADD_ASSIGN); }
+"-=" { pyylval->lex.line = yylineno; return(SUB_ASSIGN); }
+"*=" { pyylval->lex.line = yylineno; return(MUL_ASSIGN); }
+"/=" { pyylval->lex.line = yylineno; return(DIV_ASSIGN); }
+"%=" { pyylval->lex.line = yylineno; return(MOD_ASSIGN); }
+"<<=" { pyylval->lex.line = yylineno; return(LEFT_ASSIGN); }
+">>=" { pyylval->lex.line = yylineno; return(RIGHT_ASSIGN); }
+"&=" { pyylval->lex.line = yylineno; return(AND_ASSIGN); }
+"^=" { pyylval->lex.line = yylineno; return(XOR_ASSIGN); }
+"|=" { pyylval->lex.line = yylineno; return(OR_ASSIGN); }
+
+"++" { pyylval->lex.line = yylineno; return(INC_OP); }
+"--" { pyylval->lex.line = yylineno; return(DEC_OP); }
+"&&" { pyylval->lex.line = yylineno; return(AND_OP); }
+"||" { pyylval->lex.line = yylineno; return(OR_OP); }
+"^^" { pyylval->lex.line = yylineno; return(XOR_OP); }
+"<=" { pyylval->lex.line = yylineno; return(LE_OP); }
+">=" { pyylval->lex.line = yylineno; return(GE_OP); }
+"==" { pyylval->lex.line = yylineno; return(EQ_OP); }
+"!=" { pyylval->lex.line = yylineno; return(NE_OP); }
+"<<" { pyylval->lex.line = yylineno; return(LEFT_OP); }
+">>" { pyylval->lex.line = yylineno; return(RIGHT_OP); }
+";" { pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(SEMICOLON); }
+("{"|"<%") { pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(LEFT_BRACE); }
+("}"|"%>") { pyylval->lex.line = yylineno; return(RIGHT_BRACE); }
+"," { pyylval->lex.line = yylineno; if (parseContext.inTypeParen) parseContext.lexAfterType = false; return(COMMA); }
+":" { pyylval->lex.line = yylineno; return(COLON); }
+"=" { pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(EQUAL); }
+"(" { pyylval->lex.line = yylineno; parseContext.lexAfterType = false; parseContext.inTypeParen = true; return(LEFT_PAREN); }
+")" { pyylval->lex.line = yylineno; parseContext.inTypeParen = false; return(RIGHT_PAREN); }
+("["|"<:") { pyylval->lex.line = yylineno; return(LEFT_BRACKET); }
+("]"|":>") { pyylval->lex.line = yylineno; return(RIGHT_BRACKET); }
+"." { BEGIN(FIELDS); return(DOT); }
+"!" { pyylval->lex.line = yylineno; return(BANG); }
+"-" { pyylval->lex.line = yylineno; return(DASH); }
+"~" { pyylval->lex.line = yylineno; return(TILDE); }
+"+" { pyylval->lex.line = yylineno; return(PLUS); }
+"*" { pyylval->lex.line = yylineno; return(STAR); }
+"/" { pyylval->lex.line = yylineno; return(SLASH); }
+"%" { pyylval->lex.line = yylineno; return(PERCENT); }
+"<" { pyylval->lex.line = yylineno; return(LEFT_ANGLE); }
+">" { pyylval->lex.line = yylineno; return(RIGHT_ANGLE); }
+"|" { pyylval->lex.line = yylineno; return(VERTICAL_BAR); }
+"^" { pyylval->lex.line = yylineno; return(CARET); }
+"&" { pyylval->lex.line = yylineno; return(AMPERSAND); }
+"?" { pyylval->lex.line = yylineno; return(QUESTION); }
+
+<FIELDS>{L}({L}|{D})* {
+BEGIN(INITIAL);
+ pyylval->lex.line = yylineno;
+ pyylval->lex.string = NewPoolTString(yytext);
+ return FIELD_SELECTION; }
+<FIELDS>[ \t\v\f\r] {}
+
+[ \t\v\n\f\r] { }
+<*><<EOF>> { (&parseContext)->AfterEOF = true; yy_delete_buffer(YY_CURRENT_BUFFER); yyterminate();}
+<*>. { parseContext.infoSink.info << "FLEX: Unknown char " << yytext << "\n";
+ return 0; }
+
+%%
+
+
+//Including Pre-processor.
+extern "C" {
+ #include "compiler/preprocessor/preprocess.h"
+}
+
+//
+// The YY_INPUT macro just calls this. Maybe this could be just put into
+// the macro directly.
+//
+
+int yy_input(char* buf, int max_size)
+{
+ int len;
+
+ if ((len = yylex_CPP(buf, max_size)) == 0)
+ return 0;
+ if (len >= max_size)
+ YY_FATAL_ERROR( "input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+
+ buf[len] = ' ';
+ return len+1;
+}
+
+
+//
+// Parse an array of strings using yyparse. We set up globals used by
+// yywrap.
+//
+// Returns 0 for success, as per yyparse().
+//
+int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseContextLocal)
+{
+ int argv0len;
+
+ ScanFromString(argv[0]);
+
+ //Storing the Current Compiler Parse context into the cpp structure.
+ cpp->pC = (void*)&parseContextLocal;
+
+ if (!argv || argc == 0)
+ return 1;
+
+ for (int i = 0; i < argc; ++i) {
+ if (!argv[i]) {
+ parseContextLocal.error(0, "Null shader source string", "", "");
+ parseContextLocal.recover();
+ return 1;
+ }
+ }
+
+ if (!strLen) {
+ argv0len = (int) strlen(argv[0]);
+ strLen = &argv0len;
+ }
+ yyrestart(0);
+ (&parseContextLocal)->AfterEOF = false;
+ cpp->PaWhichStr = 0;
+ cpp->PaArgv = argv;
+ cpp->PaArgc = argc;
+ cpp->PaStrLen = strLen;
+ cpp->pastFirstStatement = 0;
+ yylineno = 1;
+
+ if (*cpp->PaStrLen >= 0) {
+ int ret = yyparse((void*)(&parseContextLocal));
+ if (ret || cpp->CompileError == 1 || parseContextLocal.recoveredFromError || parseContextLocal.numErrors > 0)
+ return 1;
+ else
+ return 0;
+ }
+ else
+ return 0;
+}
+
+void yyerror(const char *s)
+{
+ if (((TParseContext *)cpp->pC)->AfterEOF) {
+ if (cpp->tokensBeforeEOF == 1) {
+ GlobalParseContext->error(yylineno, "syntax error", "pre-mature EOF", s, "");
+ GlobalParseContext->recover();
+ }
+ } else {
+ GlobalParseContext->error(yylineno, "syntax error", yytext, s, "");
+ GlobalParseContext->recover();
+ }
+}
+
+void PaReservedWord()
+{
+ GlobalParseContext->error(yylineno, "Reserved word.", yytext, "", "");
+ GlobalParseContext->recover();
+}
+
+int PaIdentOrType(TString& id, TParseContext& parseContextLocal, TSymbol*& symbol)
+{
+ symbol = parseContextLocal.symbolTable.find(id);
+ if (parseContextLocal.lexAfterType == false && symbol && symbol->isVariable()) {
+ TVariable* variable = static_cast<TVariable*>(symbol);
+ if (variable->isUserType()) {
+ parseContextLocal.lexAfterType = true;
+ return TYPE_NAME;
+ }
+ }
+
+ return IDENTIFIER;
+}
+
+int PaParseComment(int &lineno, TParseContext& parseContextLocal)
+{
+ int transitionFlag = 0;
+ int nextChar;
+
+ while (transitionFlag != 2) {
+ nextChar = yyinput();
+ if (nextChar == '\n')
+ lineno++;
+ switch (nextChar) {
+ case '*' :
+ transitionFlag = 1;
+ break;
+ case '/' : /* if star is the previous character, then it is the end of comment */
+ if (transitionFlag == 1) {
+ return 1 ;
+ }
+ break;
+ case EOF :
+ /* Raise error message here */
+ parseContextLocal.error(yylineno, "End of shader found before end of comment.", "", "", "");
+ GlobalParseContext->recover();
+ return YY_NULL;
+ default : /* Any other character will be a part of the comment */
+ transitionFlag = 0;
+ }
+ }
+ return 1;
+}
+
+extern "C" {
+
+void CPPDebugLogMsg(const char *msg)
+{
+ ((TParseContext *)cpp->pC)->infoSink.debug.message(EPrefixNone, msg);
+}
+
+void CPPWarningToInfoLog(const char *msg)
+{
+ ((TParseContext *)cpp->pC)->infoSink.info.message(EPrefixWarning, msg, yylineno);
+}
+
+void CPPShInfoLogMsg(const char *msg)
+{
+ ((TParseContext *)cpp->pC)->error(yylineno,"", "",msg,"");
+ GlobalParseContext->recover();
+}
+
+void CPPErrorToInfoLog(char *msg)
+{
+ ((TParseContext *)cpp->pC)->error(yylineno,"syntax error", "",msg,"");
+ GlobalParseContext->recover();
+}
+
+void SetLineNumber(int line)
+{
+ yylineno &= ~SourceLocLineMask;
+ yylineno |= line;
+}
+
+void SetStringNumber(int string)
+{
+ yylineno = (string << SourceLocStringShift) | (yylineno & SourceLocLineMask);
+}
+
+int GetStringNumber(void)
+{
+ return yylineno >> 16;
+}
+
+int GetLineNumber(void)
+{
+ return yylineno & SourceLocLineMask;
+}
+
+void IncLineNumber(void)
+{
+ if ((yylineno & SourceLocLineMask) <= SourceLocLineMask)
+ ++yylineno;
+}
+
+void DecLineNumber(void)
+{
+ if ((yylineno & SourceLocLineMask) > 0)
+ --yylineno;
+}
+
+void HandlePragma(const char **tokens, int numTokens)
+{
+ if (!strcmp(tokens[0], "optimize")) {
+ if (numTokens != 4) {
+ CPPShInfoLogMsg("optimize pragma syntax is incorrect");
+ return;
+ }
+
+ if (strcmp(tokens[1], "(")) {
+ CPPShInfoLogMsg("\"(\" expected after 'optimize' keyword");
+ return;
+ }
+
+ if (!strcmp(tokens[2], "on"))
+ ((TParseContext *)cpp->pC)->contextPragma.optimize = true;
+ else if (!strcmp(tokens[2], "off"))
+ ((TParseContext *)cpp->pC)->contextPragma.optimize = false;
+ else {
+ CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'optimize' pragma");
+ return;
+ }
+
+ if (strcmp(tokens[3], ")")) {
+ CPPShInfoLogMsg("\")\" expected to end 'optimize' pragma");
+ return;
+ }
+ } else if (!strcmp(tokens[0], "debug")) {
+ if (numTokens != 4) {
+ CPPShInfoLogMsg("debug pragma syntax is incorrect");
+ return;
+ }
+
+ if (strcmp(tokens[1], "(")) {
+ CPPShInfoLogMsg("\"(\" expected after 'debug' keyword");
+ return;
+ }
+
+ if (!strcmp(tokens[2], "on"))
+ ((TParseContext *)cpp->pC)->contextPragma.debug = true;
+ else if (!strcmp(tokens[2], "off"))
+ ((TParseContext *)cpp->pC)->contextPragma.debug = false;
+ else {
+ CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'debug' pragma");
+ return;
+ }
+
+ if (strcmp(tokens[3], ")")) {
+ CPPShInfoLogMsg("\")\" expected to end 'debug' pragma");
+ return;
+ }
+ } else {
+
+#ifdef PRAGMA_TABLE
+ //
+ // implementation specific pragma
+ // use ((TParseContext *)cpp->pC)->contextPragma.pragmaTable to store the information about pragma
+ // For now, just ignore the pragma that the implementation cannot recognize
+ // An Example of one such implementation for a pragma that has a syntax like
+ // #pragma pragmaname(pragmavalue)
+ // This implementation stores the current pragmavalue against the pragma name in pragmaTable.
+ //
+ if (numTokens == 4 && !strcmp(tokens[1], "(") && !strcmp(tokens[3], ")")) {
+ TPragmaTable& pragmaTable = ((TParseContext *)cpp->pC)->contextPragma.pragmaTable;
+ TPragmaTable::iterator iter;
+ iter = pragmaTable.find(TString(tokens[0]));
+ if (iter != pragmaTable.end()) {
+ iter->second = tokens[2];
+ } else {
+ pragmaTable[ tokens[0] ] = tokens[2];
+ }
+ } else if (numTokens >= 2) {
+ TPragmaTable& pragmaTable = ((TParseContext *)cpp->pC)->contextPragma.pragmaTable;
+ TPragmaTable::iterator iter;
+ iter = pragmaTable.find(TString(tokens[0]));
+ if (iter != pragmaTable.end()) {
+ iter->second = tokens[1];
+ } else {
+ pragmaTable[ tokens[0] ] = tokens[1];
+ }
+ }
+#endif // PRAGMA_TABLE
+ }
+}
+
+void StoreStr(char *string)
+{
+ TString strSrc;
+ strSrc = TString(string);
+
+ ((TParseContext *)cpp->pC)->HashErrMsg = ((TParseContext *)cpp->pC)->HashErrMsg + " " + strSrc;
+}
+
+const char* GetStrfromTStr(void)
+{
+ cpp->ErrMsg = (((TParseContext *)cpp->pC)->HashErrMsg).c_str();
+ return cpp->ErrMsg;
+}
+
+void ResetTString(void)
+{
+ ((TParseContext *)cpp->pC)->HashErrMsg = "";
+}
+
+TBehavior GetBehavior(const char* behavior)
+{
+ if (!strcmp("require", behavior))
+ return EBhRequire;
+ else if (!strcmp("enable", behavior))
+ return EBhEnable;
+ else if (!strcmp("disable", behavior))
+ return EBhDisable;
+ else if (!strcmp("warn", behavior))
+ return EBhWarn;
+ else {
+ CPPShInfoLogMsg((TString("behavior '") + behavior + "' is not supported").c_str());
+ return EBhDisable;
+ }
+}
+
+void updateExtensionBehavior(const char* extName, const char* behavior)
+{
+ TBehavior behaviorVal = GetBehavior(behavior);
+ TMap<TString, TBehavior>:: iterator iter;
+ TString msg;
+
+ // special cased for all extension
+ if (!strcmp(extName, "all")) {
+ if (behaviorVal == EBhRequire || behaviorVal == EBhEnable) {
+ CPPShInfoLogMsg("extension 'all' cannot have 'require' or 'enable' behavior");
+ return;
+ } else {
+ for (iter = ((TParseContext *)cpp->pC)->extensionBehavior.begin(); iter != ((TParseContext *)cpp->pC)->extensionBehavior.end(); ++iter)
+ iter->second = behaviorVal;
+ }
+ } else {
+ iter = ((TParseContext *)cpp->pC)->extensionBehavior.find(TString(extName));
+ if (iter == ((TParseContext *)cpp->pC)->extensionBehavior.end()) {
+ switch (behaviorVal) {
+ case EBhRequire:
+ CPPShInfoLogMsg((TString("extension '") + extName + "' is not supported").c_str());
+ break;
+ case EBhEnable:
+ case EBhWarn:
+ case EBhDisable:
+ msg = TString("extension '") + extName + "' is not supported";
+ ((TParseContext *)cpp->pC)->infoSink.info.message(EPrefixWarning, msg.c_str(), yylineno);
+ break;
+ }
+ return;
+ } else
+ iter->second = behaviorVal;
+ }
+}
+
+} // extern "C"
+
+void setInitialState()
+{
+ yy_start = 1;
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/glslang.y b/Source/ThirdParty/ANGLE/src/compiler/glslang.y
new file mode 100644
index 0000000..d0d29df
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/glslang.y
@@ -0,0 +1,2178 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+/**
+ * This is bison grammar and production code for parsing the OpenGL 2.0 shading
+ * languages.
+ */
+%{
+
+/* Based on:
+ANSI C Yacc grammar
+
+In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a
+matching Lex specification) for the April 30, 1985 draft version of the
+ANSI C standard. Tom Stockfisch reposted it to net.sources in 1987; that
+original, as mentioned in the answer to question 17.25 of the comp.lang.c
+FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z.
+
+I intend to keep this version as close to the current C Standard grammar as
+possible; please let me know if you discover discrepancies.
+
+Jutta Degener, 1995
+*/
+
+#include "compiler/SymbolTable.h"
+#include "compiler/ParseHelper.h"
+#include "GLSLANG/ShaderLang.h"
+
+#define YYPARSE_PARAM parseContextLocal
+/*
+TODO(alokp): YYPARSE_PARAM_DECL is only here to support old bison.exe in
+compiler/tools. Remove it when we can exclusively use the newer version.
+*/
+#define YYPARSE_PARAM_DECL void*
+#define parseContext ((TParseContext*)(parseContextLocal))
+#define YYLEX_PARAM parseContextLocal
+#define YY_DECL int yylex(YYSTYPE* pyylval, void* parseContextLocal)
+extern void yyerror(const char*);
+
+#define FRAG_VERT_ONLY(S, L) { \
+ if (parseContext->language != EShLangFragment && \
+ parseContext->language != EShLangVertex) { \
+ parseContext->error(L, " supported in vertex/fragment shaders only ", S, "", ""); \
+ parseContext->recover(); \
+ } \
+}
+
+#define VERTEX_ONLY(S, L) { \
+ if (parseContext->language != EShLangVertex) { \
+ parseContext->error(L, " supported in vertex shaders only ", S, "", ""); \
+ parseContext->recover(); \
+ } \
+}
+
+#define FRAG_ONLY(S, L) { \
+ if (parseContext->language != EShLangFragment) { \
+ parseContext->error(L, " supported in fragment shaders only ", S, "", ""); \
+ parseContext->recover(); \
+ } \
+}
+
+#define PACK_ONLY(S, L) { \
+ if (parseContext->language != EShLangPack) { \
+ parseContext->error(L, " supported in pack shaders only ", S, "", ""); \
+ parseContext->recover(); \
+ } \
+}
+
+#define UNPACK_ONLY(S, L) { \
+ if (parseContext->language != EShLangUnpack) { \
+ parseContext->error(L, " supported in unpack shaders only ", S, "", ""); \
+ parseContext->recover(); \
+ } \
+}
+
+#define PACK_UNPACK_ONLY(S, L) { \
+ if (parseContext->language != EShLangUnpack && \
+ parseContext->language != EShLangPack) { \
+ parseContext->error(L, " supported in pack/unpack shaders only ", S, "", ""); \
+ parseContext->recover(); \
+ } \
+}
+%}
+%union {
+ struct {
+ TSourceLoc line;
+ union {
+ TString *string;
+ float f;
+ int i;
+ bool b;
+ };
+ TSymbol* symbol;
+ } lex;
+ struct {
+ TSourceLoc line;
+ TOperator op;
+ union {
+ TIntermNode* intermNode;
+ TIntermNodePair nodePair;
+ TIntermTyped* intermTypedNode;
+ TIntermAggregate* intermAggregate;
+ };
+ union {
+ TPublicType type;
+ TPrecision precision;
+ TQualifier qualifier;
+ TFunction* function;
+ TParameter param;
+ TTypeLine typeLine;
+ TTypeList* typeList;
+ };
+ } interm;
+}
+
+%{
+ extern int yylex(YYSTYPE*, void*);
+%}
+
+%pure_parser /* Just in case is called from multiple threads */
+%expect 1 /* One shift reduce conflict because of if | else */
+%token <lex> INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION
+%token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE
+%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN
+%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4
+%token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING
+%token <lex> STRUCT VOID_TYPE WHILE
+%token <lex> SAMPLER2D SAMPLERCUBE
+
+%token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT
+%token <lex> FIELD_SELECTION
+%token <lex> LEFT_OP RIGHT_OP
+%token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
+%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
+%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
+%token <lex> SUB_ASSIGN
+
+%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
+%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
+%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
+
+%type <interm> assignment_operator unary_operator
+%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
+%type <interm.intermTypedNode> expression integer_expression assignment_expression
+%type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
+%type <interm.intermTypedNode> relational_expression equality_expression
+%type <interm.intermTypedNode> conditional_expression constant_expression
+%type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
+%type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
+%type <interm.intermTypedNode> function_call initializer condition conditionopt
+
+%type <interm.intermNode> translation_unit function_definition
+%type <interm.intermNode> statement simple_statement
+%type <interm.intermAggregate> statement_list compound_statement
+%type <interm.intermNode> declaration_statement selection_statement expression_statement
+%type <interm.intermNode> declaration external_declaration
+%type <interm.intermNode> for_init_statement compound_statement_no_new_scope
+%type <interm.nodePair> selection_rest_statement for_rest_statement
+%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope
+%type <interm> single_declaration init_declarator_list
+
+%type <interm> parameter_declaration parameter_declarator parameter_type_specifier
+%type <interm.qualifier> parameter_qualifier
+
+%type <interm.precision> precision_qualifier
+%type <interm.type> type_qualifier fully_specified_type type_specifier
+%type <interm.type> type_specifier_no_prec type_specifier_nonarray
+%type <interm.type> struct_specifier
+%type <interm.typeLine> struct_declarator
+%type <interm.typeList> struct_declarator_list struct_declaration struct_declaration_list
+%type <interm.function> function_header function_declarator function_identifier
+%type <interm.function> function_header_with_parameters function_call_header
+%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
+%type <interm> function_call_or_method
+
+%start translation_unit
+%%
+
+variable_identifier
+ : IDENTIFIER {
+ // The symbol table search was done in the lexical phase
+ const TSymbol* symbol = $1.symbol;
+ const TVariable* variable;
+ if (symbol == 0) {
+ parseContext->error($1.line, "undeclared identifier", $1.string->c_str(), "");
+ parseContext->recover();
+ TType type(EbtFloat, EbpUndefined);
+ TVariable* fakeVariable = new TVariable($1.string, type);
+ parseContext->symbolTable.insert(*fakeVariable);
+ variable = fakeVariable;
+ } else {
+ // This identifier can only be a variable type symbol
+ if (! symbol->isVariable()) {
+ parseContext->error($1.line, "variable expected", $1.string->c_str(), "");
+ parseContext->recover();
+ }
+ variable = static_cast<const TVariable*>(symbol);
+ }
+
+ // don't delete $1.string, it's used by error recovery, and the pool
+ // pop will reclaim the memory
+
+ if (variable->getType().getQualifier() == EvqConst ) {
+ ConstantUnion* constArray = variable->getConstPointer();
+ TType t(variable->getType());
+ $$ = parseContext->intermediate.addConstantUnion(constArray, t, $1.line);
+ } else
+ $$ = parseContext->intermediate.addSymbol(variable->getUniqueId(),
+ variable->getName(),
+ variable->getType(), $1.line);
+ }
+ ;
+
+primary_expression
+ : variable_identifier {
+ $$ = $1;
+ }
+ | INTCONSTANT {
+ //
+ // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders,
+ // check for overflow for constants
+ //
+ if (abs($1.i) >= (1 << 16)) {
+ parseContext->error($1.line, " integer constant overflow", "", "");
+ parseContext->recover();
+ }
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setIConst($1.i);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $1.line);
+ }
+ | FLOATCONSTANT {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setFConst($1.f);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line);
+ }
+ | BOOLCONSTANT {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst($1.b);
+ $$ = parseContext->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())
+ parseContext->error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str(), "");
+ else
+ parseContext->error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression", "");
+ parseContext->recover();
+ }
+ if ($1->getType().getQualifier() == EvqConst && $3->getQualifier() == EvqConst) {
+ if ($1->isArray()) { // constant folding for arrays
+ $$ = parseContext->addConstArrayNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line);
+ } else if ($1->isVector()) { // constant folding for vectors
+ TVectorFields fields;
+ fields.num = 1;
+ fields.offsets[0] = $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(); // need to do it this way because v.xy sends fields integer array
+ $$ = parseContext->addConstVectorNode(fields, $1, $2.line);
+ } else if ($1->isMatrix()) { // constant folding for matrices
+ $$ = parseContext->addConstMatrixNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line);
+ }
+ } else {
+ if ($3->getQualifier() == EvqConst) {
+ if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() && !$1->isArray() ) {
+ parseContext->error($2.line, "", "[", "field selection out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst());
+ parseContext->recover();
+ } else {
+ if ($1->isArray()) {
+ if ($1->getType().getArraySize() == 0) {
+ if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()) {
+ if (parseContext->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, $2.line))
+ parseContext->recover();
+ } else {
+ if (parseContext->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line))
+ parseContext->recover();
+ }
+ } else if ( $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= $1->getType().getArraySize()) {
+ parseContext->error($2.line, "", "[", "array index out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst());
+ parseContext->recover();
+ }
+ }
+ $$ = parseContext->intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line);
+ }
+ } else {
+ if ($1->isArray() && $1->getType().getArraySize() == 0) {
+ parseContext->error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable");
+ parseContext->recover();
+ }
+
+ $$ = parseContext->intermediate.addIndex(EOpIndexIndirect, $1, $3, $2.line);
+ }
+ }
+ if ($$ == 0) {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setFConst(0.0f);
+ $$ = parseContext->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()) {
+ parseContext->error($3.line, "cannot apply dot operator to an array", ".", "");
+ parseContext->recover();
+ }
+
+ if ($1->isVector()) {
+ TVectorFields fields;
+ if (! parseContext->parseVectorFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
+ fields.num = 1;
+ fields.offsets[0] = 0;
+ parseContext->recover();
+ }
+
+ if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields
+ $$ = parseContext->addConstVectorNode(fields, $1, $3.line);
+ if ($$ == 0) {
+ parseContext->recover();
+ $$ = $1;
+ }
+ else
+ $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size()));
+ } else {
+ if (fields.num == 1) {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setIConst(fields.offsets[0]);
+ TIntermTyped* index = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
+ $$ = parseContext->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+ $$->setType(TType($1->getBasicType(), $1->getPrecision()));
+ } else {
+ TString vectorString = *$3.string;
+ TIntermTyped* index = parseContext->intermediate.addSwizzle(fields, $3.line);
+ $$ = parseContext->intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line);
+ $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size()));
+ }
+ }
+ } else if ($1->isMatrix()) {
+ TMatrixFields fields;
+ if (! parseContext->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
+ fields.wholeRow = false;
+ fields.wholeCol = false;
+ fields.row = 0;
+ fields.col = 0;
+ parseContext->recover();
+ }
+
+ if (fields.wholeRow || fields.wholeCol) {
+ parseContext->error($2.line, " non-scalar fields not implemented yet", ".", "");
+ parseContext->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setIConst(0);
+ TIntermTyped* index = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
+ $$ = parseContext->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 = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
+ $$ = parseContext->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) {
+ parseContext->error($2.line, "structure has no fields", "Internal Error", "");
+ parseContext->recover();
+ $$ = $1;
+ } else {
+ unsigned int i;
+ for (i = 0; i < fields->size(); ++i) {
+ if ((*fields)[i].type->getFieldName() == *$3.string) {
+ fieldFound = true;
+ break;
+ }
+ }
+ if (fieldFound) {
+ if ($1->getType().getQualifier() == EvqConst) {
+ $$ = parseContext->addConstStruct(*$3.string, $1, $2.line);
+ if ($$ == 0) {
+ parseContext->recover();
+ $$ = $1;
+ }
+ else {
+ $$->setType(*(*fields)[i].type);
+ // change the qualifier of the return type, not of the structure field
+ // as the structure definition is shared between various structures.
+ $$->getTypePointer()->setQualifier(EvqConst);
+ }
+ } else {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setIConst(i);
+ TIntermTyped* index = parseContext->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, $3.line);
+ $$ = parseContext->intermediate.addIndex(EOpIndexDirectStruct, $1, index, $2.line);
+ $$->setType(*(*fields)[i].type);
+ }
+ } else {
+ parseContext->error($2.line, " no such field in structure", $3.string->c_str(), "");
+ parseContext->recover();
+ $$ = $1;
+ }
+ }
+ } else {
+ parseContext->error($2.line, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str(), "");
+ parseContext->recover();
+ $$ = $1;
+ }
+ // don't delete $3.string, it's from the pool
+ }
+ | postfix_expression INC_OP {
+ if (parseContext->lValueErrorCheck($2.line, "++", $1))
+ parseContext->recover();
+ $$ = parseContext->intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->unaryOpError($2.line, "++", $1->getCompleteString());
+ parseContext->recover();
+ $$ = $1;
+ }
+ }
+ | postfix_expression DEC_OP {
+ if (parseContext->lValueErrorCheck($2.line, "--", $1))
+ parseContext->recover();
+ $$ = parseContext->intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->unaryOpError($2.line, "--", $1->getCompleteString());
+ parseContext->recover();
+ $$ = $1;
+ }
+ }
+ ;
+
+integer_expression
+ : expression {
+ if (parseContext->integerErrorCheck($1, "[]"))
+ parseContext->recover();
+ $$ = $1;
+ }
+ ;
+
+function_call
+ : function_call_or_method {
+ TFunction* fnCall = $1.function;
+ TOperator op = fnCall->getBuiltInOp();
+
+ if (op != 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 (parseContext->constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) {
+ $$ = 0;
+ } else {
+ //
+ // It's a constructor, of type 'type'.
+ //
+ $$ = parseContext->addConstructor($1.intermNode, &type, op, fnCall, $1.line);
+ }
+
+ if ($$ == 0) {
+ parseContext->recover();
+ $$ = parseContext->intermediate.setAggregateOperator(0, op, $1.line);
+ }
+ $$->setType(type);
+ } else {
+ //
+ // Not a constructor. Find it in the symbol table.
+ //
+ const TFunction* fnCandidate;
+ bool builtIn;
+ fnCandidate = parseContext->findFunction($1.line, fnCall, &builtIn);
+ if (fnCandidate) {
+ //
+ // A declared function. But, it might still map to a built-in
+ // operation.
+ //
+ op = fnCandidate->getBuiltInOp();
+ if (builtIn && op != EOpNull) {
+ //
+ // A function call mapped to a built-in operation.
+ //
+ if (fnCandidate->getParamCount() == 1) {
+ //
+ // Treat it like a built-in unary operator.
+ //
+ $$ = parseContext->intermediate.addUnaryMath(op, $1.intermNode, 0, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->error($1.intermNode->getLine(), " wrong operand type", "Internal Error",
+ "built in unary operator function. Type: %s",
+ static_cast<TIntermTyped*>($1.intermNode)->getCompleteString().c_str());
+ YYERROR;
+ }
+ } else {
+ $$ = parseContext->intermediate.setAggregateOperator($1.intermAggregate, op, $1.line);
+ }
+ } else {
+ // This is a real function call
+
+ $$ = parseContext->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, $1.line);
+ $$->setType(fnCandidate->getReturnType());
+
+ // this is how we know whether the given function is a builtIn function or a user defined function
+ // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
+ // if builtIn == true, it's definitely a builtIn function with EOpNull
+ if (!builtIn)
+ $$->getAsAggregate()->setUserDefined();
+ $$->getAsAggregate()->setName(fnCandidate->getMangledName());
+
+ TQualifier qual;
+ TQualifierList& qualifierList = $$->getAsAggregate()->getQualifier();
+ for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
+ qual = (*fnCandidate)[i].type->getQualifier();
+ if (qual == EvqOut || qual == EvqInOut) {
+ if (parseContext->lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) {
+ parseContext->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", "");
+ parseContext->recover();
+ }
+ }
+ qualifierList.push_back(qual);
+ }
+ }
+ $$->setType(fnCandidate->getReturnType());
+ } else {
+ // error message was put out by PaFindFunction()
+ // Put on a dummy node for error recovery
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setFConst(0.0f);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line);
+ parseContext->recover();
+ }
+ }
+ delete fnCall;
+ }
+ ;
+
+function_call_or_method
+ : function_call_generic {
+ $$ = $1;
+ }
+ | postfix_expression DOT function_call_generic {
+ parseContext->error($3.line, "methods are not supported", "", "");
+ parseContext->recover();
+ $$ = $3;
+ }
+ ;
+
+function_call_generic
+ : function_call_header_with_parameters RIGHT_PAREN {
+ $$ = $1;
+ $$.line = $2.line;
+ }
+ | function_call_header_no_parameters RIGHT_PAREN {
+ $$ = $1;
+ $$.line = $2.line;
+ }
+ ;
+
+function_call_header_no_parameters
+ : function_call_header VOID_TYPE {
+ $$.function = $1;
+ $$.intermNode = 0;
+ }
+ | function_call_header {
+ $$.function = $1;
+ $$.intermNode = 0;
+ }
+ ;
+
+function_call_header_with_parameters
+ : function_call_header assignment_expression {
+ TParameter param = { 0, new TType($2->getType()) };
+ $1->addParameter(param);
+ $$.function = $1;
+ $$.intermNode = $2;
+ }
+ | function_call_header_with_parameters COMMA assignment_expression {
+ TParameter param = { 0, new TType($3->getType()) };
+ $1.function->addParameter(param);
+ $$.function = $1.function;
+ $$.intermNode = parseContext->intermediate.growAggregate($1.intermNode, $3, $2.line);
+ }
+ ;
+
+function_call_header
+ : function_identifier LEFT_PAREN {
+ $$ = $1;
+ }
+ ;
+
+// Grammar Note: Constructors look like functions, but are recognized as types.
+
+function_identifier
+ : type_specifier {
+ //
+ // Constructor
+ //
+ if ($1.array) {
+ if (parseContext->extensionErrorCheck($1.line, "GL_3DL_array_objects")) {
+ parseContext->recover();
+ $1.setArray(false);
+ }
+ }
+
+ if ($1.userDef) {
+ TString tempString = "";
+ TType type($1);
+ TFunction *function = new TFunction(&tempString, type, EOpConstructStruct);
+ $$ = function;
+ } else {
+ TOperator op = EOpNull;
+ switch ($1.type) {
+ case EbtFloat:
+ if ($1.matrix) {
+ switch($1.size) {
+ case 2: op = EOpConstructMat2; break;
+ case 3: op = EOpConstructMat3; break;
+ case 4: op = EOpConstructMat4; break;
+ }
+ } else {
+ switch($1.size) {
+ case 1: op = EOpConstructFloat; break;
+ case 2: op = EOpConstructVec2; break;
+ case 3: op = EOpConstructVec3; break;
+ case 4: op = EOpConstructVec4; break;
+ }
+ }
+ break;
+ case EbtInt:
+ switch($1.size) {
+ case 1: op = EOpConstructInt; break;
+ case 2: FRAG_VERT_ONLY("ivec2", $1.line); op = EOpConstructIVec2; break;
+ case 3: FRAG_VERT_ONLY("ivec3", $1.line); op = EOpConstructIVec3; break;
+ case 4: FRAG_VERT_ONLY("ivec4", $1.line); op = EOpConstructIVec4; break;
+ }
+ break;
+ case EbtBool:
+ switch($1.size) {
+ case 1: op = EOpConstructBool; break;
+ case 2: FRAG_VERT_ONLY("bvec2", $1.line); op = EOpConstructBVec2; break;
+ case 3: FRAG_VERT_ONLY("bvec3", $1.line); op = EOpConstructBVec3; break;
+ case 4: FRAG_VERT_ONLY("bvec4", $1.line); op = EOpConstructBVec4; break;
+ }
+ break;
+ }
+ if (op == EOpNull) {
+ parseContext->error($1.line, "cannot construct this type", getBasicString($1.type), "");
+ parseContext->recover();
+ $1.type = EbtFloat;
+ op = EOpConstructFloat;
+ }
+ TString tempString = "";
+ TType type($1);
+ TFunction *function = new TFunction(&tempString, type, op);
+ $$ = function;
+ }
+ }
+ | IDENTIFIER {
+ if (parseContext->reservedErrorCheck($1.line, *$1.string))
+ parseContext->recover();
+ TType type(EbtVoid, EbpUndefined);
+ TFunction *function = new TFunction($1.string, type);
+ $$ = function;
+ }
+ | FIELD_SELECTION {
+ if (parseContext->reservedErrorCheck($1.line, *$1.string))
+ parseContext->recover();
+ TType type(EbtVoid, EbpUndefined);
+ TFunction *function = new TFunction($1.string, type);
+ $$ = function;
+ }
+ ;
+
+unary_expression
+ : postfix_expression {
+ $$ = $1;
+ }
+ | INC_OP unary_expression {
+ if (parseContext->lValueErrorCheck($1.line, "++", $2))
+ parseContext->recover();
+ $$ = parseContext->intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->unaryOpError($1.line, "++", $2->getCompleteString());
+ parseContext->recover();
+ $$ = $2;
+ }
+ }
+ | DEC_OP unary_expression {
+ if (parseContext->lValueErrorCheck($1.line, "--", $2))
+ parseContext->recover();
+ $$ = parseContext->intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->unaryOpError($1.line, "--", $2->getCompleteString());
+ parseContext->recover();
+ $$ = $2;
+ }
+ }
+ | unary_operator unary_expression {
+ if ($1.op != EOpNull) {
+ $$ = parseContext->intermediate.addUnaryMath($1.op, $2, $1.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ const char* errorOp = "";
+ switch($1.op) {
+ case EOpNegative: errorOp = "-"; break;
+ case EOpLogicalNot: errorOp = "!"; break;
+ default: break;
+ }
+ parseContext->unaryOpError($1.line, errorOp, $2->getCompleteString());
+ parseContext->recover();
+ $$ = $2;
+ }
+ } else
+ $$ = $2;
+ }
+ ;
+// Grammar Note: No traditional style type casts.
+
+unary_operator
+ : PLUS { $$.line = $1.line; $$.op = EOpNull; }
+ | DASH { $$.line = $1.line; $$.op = EOpNegative; }
+ | BANG { $$.line = $1.line; $$.op = EOpLogicalNot; }
+ ;
+// Grammar Note: No '*' or '&' unary ops. Pointers are not supported.
+
+multiplicative_expression
+ : unary_expression { $$ = $1; }
+ | multiplicative_expression STAR unary_expression {
+ FRAG_VERT_ONLY("*", $2.line);
+ $$ = parseContext->intermediate.addBinaryMath(EOpMul, $1, $3, $2.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString());
+ parseContext->recover();
+ $$ = $1;
+ }
+ }
+ | multiplicative_expression SLASH unary_expression {
+ FRAG_VERT_ONLY("/", $2.line);
+ $$ = parseContext->intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString());
+ parseContext->recover();
+ $$ = $1;
+ }
+ }
+ ;
+
+additive_expression
+ : multiplicative_expression { $$ = $1; }
+ | additive_expression PLUS multiplicative_expression {
+ $$ = parseContext->intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString());
+ parseContext->recover();
+ $$ = $1;
+ }
+ }
+ | additive_expression DASH multiplicative_expression {
+ $$ = parseContext->intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString());
+ parseContext->recover();
+ $$ = $1;
+ }
+ }
+ ;
+
+shift_expression
+ : additive_expression { $$ = $1; }
+ ;
+
+relational_expression
+ : shift_expression { $$ = $1; }
+ | relational_expression LEFT_ANGLE shift_expression {
+ $$ = parseContext->intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString());
+ parseContext->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ }
+ }
+ | relational_expression RIGHT_ANGLE shift_expression {
+ $$ = parseContext->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString());
+ parseContext->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ }
+ }
+ | relational_expression LE_OP shift_expression {
+ $$ = parseContext->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString());
+ parseContext->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ }
+ }
+ | relational_expression GE_OP shift_expression {
+ $$ = parseContext->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString());
+ parseContext->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ }
+ }
+ ;
+
+equality_expression
+ : relational_expression { $$ = $1; }
+ | equality_expression EQ_OP relational_expression {
+ $$ = parseContext->intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString());
+ parseContext->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ } else if (($1->isArray() || $3->isArray()) && parseContext->extensionErrorCheck($2.line, "GL_3DL_array_objects"))
+ parseContext->recover();
+ }
+ | equality_expression NE_OP relational_expression {
+ $$ = parseContext->intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString());
+ parseContext->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ } else if (($1->isArray() || $3->isArray()) && parseContext->extensionErrorCheck($2.line, "GL_3DL_array_objects"))
+ parseContext->recover();
+ }
+ ;
+
+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 {
+ $$ = parseContext->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString());
+ parseContext->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ }
+ }
+ ;
+
+logical_xor_expression
+ : logical_and_expression { $$ = $1; }
+ | logical_xor_expression XOR_OP logical_and_expression {
+ $$ = parseContext->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString());
+ parseContext->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ }
+ }
+ ;
+
+logical_or_expression
+ : logical_xor_expression { $$ = $1; }
+ | logical_or_expression OR_OP logical_xor_expression {
+ $$ = parseContext->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line, parseContext->symbolTable);
+ if ($$ == 0) {
+ parseContext->binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString());
+ parseContext->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ }
+ }
+ ;
+
+conditional_expression
+ : logical_or_expression { $$ = $1; }
+ | logical_or_expression QUESTION expression COLON assignment_expression {
+ if (parseContext->boolErrorCheck($2.line, $1))
+ parseContext->recover();
+
+ $$ = parseContext->intermediate.addSelection($1, $3, $5, $2.line);
+ if ($3->getType() != $5->getType())
+ $$ = 0;
+
+ if ($$ == 0) {
+ parseContext->binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString());
+ parseContext->recover();
+ $$ = $5;
+ }
+ }
+ ;
+
+assignment_expression
+ : conditional_expression { $$ = $1; }
+ | unary_expression assignment_operator assignment_expression {
+ if (parseContext->lValueErrorCheck($2.line, "assign", $1))
+ parseContext->recover();
+ $$ = parseContext->intermediate.addAssign($2.op, $1, $3, $2.line);
+ if ($$ == 0) {
+ parseContext->assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString());
+ parseContext->recover();
+ $$ = $1;
+ } else if (($1->isArray() || $3->isArray()) && parseContext->extensionErrorCheck($2.line, "GL_3DL_array_objects"))
+ parseContext->recover();
+ }
+ ;
+
+assignment_operator
+ : EQUAL { $$.line = $1.line; $$.op = EOpAssign; }
+ | MUL_ASSIGN { FRAG_VERT_ONLY("*=", $1.line); $$.line = $1.line; $$.op = EOpMulAssign; }
+ | DIV_ASSIGN { FRAG_VERT_ONLY("/=", $1.line); $$.line = $1.line; $$.op = EOpDivAssign; }
+ | ADD_ASSIGN { $$.line = $1.line; $$.op = EOpAddAssign; }
+ | SUB_ASSIGN { $$.line = $1.line; $$.op = EOpSubAssign; }
+ ;
+
+expression
+ : assignment_expression {
+ $$ = $1;
+ }
+ | expression COMMA assignment_expression {
+ $$ = parseContext->intermediate.addComma($1, $3, $2.line);
+ if ($$ == 0) {
+ parseContext->binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString());
+ parseContext->recover();
+ $$ = $3;
+ }
+ }
+ ;
+
+constant_expression
+ : conditional_expression {
+ if (parseContext->constErrorCheck($1))
+ parseContext->recover();
+ $$ = $1;
+ }
+ ;
+
+declaration
+ : function_prototype SEMICOLON {
+ TFunction &function = *($1.function);
+
+ TIntermAggregate *prototype = new TIntermAggregate;
+ prototype->setType(function.getReturnType());
+ prototype->setName(function.getName());
+
+ for (int i = 0; i < function.getParamCount(); i++)
+ {
+ TParameter &param = function[i];
+ if (param.name != 0)
+ {
+ TVariable *variable = new TVariable(param.name, *param.type);
+
+ prototype = parseContext->intermediate.growAggregate(prototype, parseContext->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), $1.line), $1.line);
+ }
+ else
+ {
+ prototype = parseContext->intermediate.growAggregate(prototype, parseContext->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
+ }
+ }
+
+ prototype->setOp(EOpPrototype);
+ $$ = prototype;
+ }
+ | init_declarator_list SEMICOLON {
+ if ($1.intermAggregate)
+ $1.intermAggregate->setOp(EOpDeclaration);
+ $$ = $1.intermAggregate;
+ }
+ | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
+ parseContext->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*>(parseContext->symbolTable.find($1->getMangledName()));
+ if (prevDec) {
+ if (prevDec->getReturnType() != $1->getReturnType()) {
+ parseContext->error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString(), "");
+ parseContext->recover();
+ }
+ for (int i = 0; i < prevDec->getParamCount(); ++i) {
+ if ((*prevDec)[i].type->getQualifier() != (*$1)[i].type->getQualifier()) {
+ parseContext->error($2.line, "overloaded functions must have the same parameter qualifiers", (*$1)[i].type->getQualifierString(), "");
+ parseContext->recover();
+ }
+ }
+ }
+
+ //
+ // If this is a redeclaration, it could also be a definition,
+ // in which case, we want to use the variable names from this one, and not the one that's
+ // being redeclared. So, pass back up this declaration, not the one in the symbol table.
+ //
+ $$.function = $1;
+ $$.line = $2.line;
+
+ parseContext->symbolTable.insert(*$$.function);
+ }
+ ;
+
+function_declarator
+ : function_header {
+ $$ = $1;
+ }
+ | function_header_with_parameters {
+ $$ = $1;
+ }
+ ;
+
+
+function_header_with_parameters
+ : function_header parameter_declaration {
+ // Add the parameter
+ $$ = $1;
+ if ($2.param.type->getBasicType() != EbtVoid)
+ $1->addParameter($2.param);
+ else
+ delete $2.param.type;
+ }
+ | function_header_with_parameters COMMA parameter_declaration {
+ //
+ // Only first parameter of one-parameter functions can be void
+ // The check for named parameters not being void is done in parameter_declarator
+ //
+ if ($3.param.type->getBasicType() == EbtVoid) {
+ //
+ // This parameter > first is void
+ //
+ parseContext->error($2.line, "cannot be an argument type except for '(void)'", "void", "");
+ parseContext->recover();
+ delete $3.param.type;
+ } else {
+ // Add the parameter
+ $$ = $1;
+ $1->addParameter($3.param);
+ }
+ }
+ ;
+
+function_header
+ : fully_specified_type IDENTIFIER LEFT_PAREN {
+ if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) {
+ parseContext->error($2.line, "no qualifiers allowed for function return", getQualifierString($1.qualifier), "");
+ parseContext->recover();
+ }
+ // make sure a sampler is not involved as well...
+ if (parseContext->structQualifierErrorCheck($2.line, $1))
+ parseContext->recover();
+
+ // Add the function as a prototype after parsing it (we do not support recursion)
+ TFunction *function;
+ TType type($1);
+ function = new TFunction($2.string, type);
+ $$ = function;
+ }
+ ;
+
+parameter_declarator
+ // Type + name
+ : type_specifier IDENTIFIER {
+ if ($1.type == EbtVoid) {
+ parseContext->error($2.line, "illegal use of type 'void'", $2.string->c_str(), "");
+ parseContext->recover();
+ }
+ if (parseContext->reservedErrorCheck($2.line, *$2.string))
+ parseContext->recover();
+ TParameter param = {$2.string, new TType($1)};
+ $$.line = $2.line;
+ $$.param = param;
+ }
+ | type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ // Check that we can make an array out of this type
+ if (parseContext->arrayTypeErrorCheck($3.line, $1))
+ parseContext->recover();
+
+ if (parseContext->reservedErrorCheck($2.line, *$2.string))
+ parseContext->recover();
+
+ int size;
+ if (parseContext->arraySizeErrorCheck($3.line, $4, size))
+ parseContext->recover();
+ $1.setArray(true, size);
+
+ TType* type = new TType($1);
+ TParameter param = { $2.string, type };
+ $$.line = $2.line;
+ $$.param = param;
+ }
+ ;
+
+parameter_declaration
+ //
+ // The only parameter qualifier a parameter can have are
+ // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST.
+ //
+
+ //
+ // Type + name
+ //
+ : type_qualifier parameter_qualifier parameter_declarator {
+ $$ = $3;
+ if (parseContext->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
+ parseContext->recover();
+ }
+ | parameter_qualifier parameter_declarator {
+ $$ = $2;
+ if (parseContext->parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
+ parseContext->recover();
+ if (parseContext->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
+ parseContext->recover();
+ }
+ //
+ // Only type
+ //
+ | type_qualifier parameter_qualifier parameter_type_specifier {
+ $$ = $3;
+ if (parseContext->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
+ parseContext->recover();
+ }
+ | parameter_qualifier parameter_type_specifier {
+ $$ = $2;
+ if (parseContext->parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
+ parseContext->recover();
+ if (parseContext->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
+ parseContext->recover();
+ }
+ ;
+
+parameter_qualifier
+ : /* empty */ {
+ $$ = EvqIn;
+ }
+ | IN_QUAL {
+ $$ = EvqIn;
+ }
+ | OUT_QUAL {
+ $$ = EvqOut;
+ }
+ | INOUT_QUAL {
+ $$ = EvqInOut;
+ }
+ ;
+
+parameter_type_specifier
+ : type_specifier {
+ TParameter param = { 0, new TType($1) };
+ $$.param = param;
+ }
+ ;
+
+init_declarator_list
+ : single_declaration {
+ $$ = $1;
+
+ if ($$.type.precision == EbpUndefined) {
+ $$.type.precision = parseContext->symbolTable.getDefaultPrecision($1.type.type);
+ if (parseContext->precisionErrorCheck($1.line, $$.type.precision, $1.type.type)) {
+ parseContext->recover();
+ }
+ }
+ }
+ | init_declarator_list COMMA IDENTIFIER {
+ $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, parseContext->intermediate.addSymbol(0, *$3.string, TType($1.type), $3.line), $3.line);
+
+ if (parseContext->structQualifierErrorCheck($3.line, $$.type))
+ parseContext->recover();
+
+ if (parseContext->nonInitConstErrorCheck($3.line, *$3.string, $$.type))
+ parseContext->recover();
+
+ if (parseContext->nonInitErrorCheck($3.line, *$3.string, $$.type))
+ parseContext->recover();
+ }
+ | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
+ if (parseContext->structQualifierErrorCheck($3.line, $1.type))
+ parseContext->recover();
+
+ if (parseContext->nonInitConstErrorCheck($3.line, *$3.string, $1.type))
+ parseContext->recover();
+
+ $$ = $1;
+
+ if (parseContext->arrayTypeErrorCheck($4.line, $1.type) || parseContext->arrayQualifierErrorCheck($4.line, $1.type))
+ parseContext->recover();
+ else {
+ $1.type.setArray(true);
+ TVariable* variable;
+ if (parseContext->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+ parseContext->recover();
+ }
+ }
+ | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ if (parseContext->structQualifierErrorCheck($3.line, $1.type))
+ parseContext->recover();
+
+ if (parseContext->nonInitConstErrorCheck($3.line, *$3.string, $1.type))
+ parseContext->recover();
+
+ $$ = $1;
+
+ if (parseContext->arrayTypeErrorCheck($4.line, $1.type) || parseContext->arrayQualifierErrorCheck($4.line, $1.type))
+ parseContext->recover();
+ else {
+ int size;
+ if (parseContext->arraySizeErrorCheck($4.line, $5, size))
+ parseContext->recover();
+ $1.type.setArray(true, size);
+ TVariable* variable;
+ if (parseContext->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+ parseContext->recover();
+ TType type = TType($1.type);
+ type.setArraySize(size);
+ $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, parseContext->intermediate.addSymbol(0, *$3.string, type, $3.line), $3.line);
+ }
+ }
+ | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET EQUAL initializer {
+ if (parseContext->structQualifierErrorCheck($3.line, $1.type))
+ parseContext->recover();
+
+ $$ = $1;
+
+ TVariable* variable = 0;
+ if (parseContext->arrayTypeErrorCheck($4.line, $1.type) || parseContext->arrayQualifierErrorCheck($4.line, $1.type))
+ parseContext->recover();
+ else {
+ $1.type.setArray(true, $7->getType().getArraySize());
+ if (parseContext->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+ parseContext->recover();
+ }
+
+ if (parseContext->extensionErrorCheck($$.line, "GL_3DL_array_objects"))
+ parseContext->recover();
+ else {
+ TIntermNode* intermNode;
+ if (!parseContext->executeInitializer($3.line, *$3.string, $1.type, $7, intermNode, variable)) {
+ //
+ // build the intermediate representation
+ //
+ if (intermNode)
+ $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, intermNode, $6.line);
+ else
+ $$.intermAggregate = $1.intermAggregate;
+ } else {
+ parseContext->recover();
+ $$.intermAggregate = 0;
+ }
+ }
+ }
+ | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer {
+ if (parseContext->structQualifierErrorCheck($3.line, $1.type))
+ parseContext->recover();
+
+ $$ = $1;
+
+ TVariable* variable = 0;
+ if (parseContext->arrayTypeErrorCheck($4.line, $1.type) || parseContext->arrayQualifierErrorCheck($4.line, $1.type))
+ parseContext->recover();
+ else {
+ int size;
+ if (parseContext->arraySizeErrorCheck($4.line, $5, size))
+ parseContext->recover();
+ $1.type.setArray(true, size);
+ if (parseContext->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+ parseContext->recover();
+ }
+
+ if (parseContext->extensionErrorCheck($$.line, "GL_3DL_array_objects"))
+ parseContext->recover();
+ else {
+ TIntermNode* intermNode;
+ if (!parseContext->executeInitializer($3.line, *$3.string, $1.type, $8, intermNode, variable)) {
+ //
+ // build the intermediate representation
+ //
+ if (intermNode)
+ $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, intermNode, $7.line);
+ else
+ $$.intermAggregate = $1.intermAggregate;
+ } else {
+ parseContext->recover();
+ $$.intermAggregate = 0;
+ }
+ }
+ }
+ | init_declarator_list COMMA IDENTIFIER EQUAL initializer {
+ if (parseContext->structQualifierErrorCheck($3.line, $1.type))
+ parseContext->recover();
+
+ $$ = $1;
+
+ TIntermNode* intermNode;
+ if (!parseContext->executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) {
+ //
+ // build the intermediate representation
+ //
+ if (intermNode)
+ $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, intermNode, $4.line);
+ else
+ $$.intermAggregate = $1.intermAggregate;
+ } else {
+ parseContext->recover();
+ $$.intermAggregate = 0;
+ }
+ }
+ ;
+
+single_declaration
+ : fully_specified_type {
+ $$.type = $1;
+ $$.intermAggregate = parseContext->intermediate.makeAggregate(parseContext->intermediate.addSymbol(0, "", TType($1), $1.line), $1.line);
+ }
+ | fully_specified_type IDENTIFIER {
+ $$.intermAggregate = parseContext->intermediate.makeAggregate(parseContext->intermediate.addSymbol(0, *$2.string, TType($1), $2.line), $2.line);
+
+ if (parseContext->structQualifierErrorCheck($2.line, $$.type))
+ parseContext->recover();
+
+ if (parseContext->nonInitConstErrorCheck($2.line, *$2.string, $$.type))
+ parseContext->recover();
+
+ $$.type = $1;
+
+ if (parseContext->nonInitErrorCheck($2.line, *$2.string, $$.type))
+ parseContext->recover();
+ }
+ | fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
+ $$.intermAggregate = parseContext->intermediate.makeAggregate(parseContext->intermediate.addSymbol(0, *$2.string, TType($1), $2.line), $2.line);
+
+ if (parseContext->structQualifierErrorCheck($2.line, $1))
+ parseContext->recover();
+
+ if (parseContext->nonInitConstErrorCheck($2.line, *$2.string, $1))
+ parseContext->recover();
+
+ $$.type = $1;
+
+ if (parseContext->arrayTypeErrorCheck($3.line, $1) || parseContext->arrayQualifierErrorCheck($3.line, $1))
+ parseContext->recover();
+ else {
+ $1.setArray(true);
+ TVariable* variable;
+ if (parseContext->arrayErrorCheck($3.line, *$2.string, $1, variable))
+ parseContext->recover();
+ }
+ }
+ | fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ TType type = TType($1);
+ int size;
+ if (parseContext->arraySizeErrorCheck($2.line, $4, size))
+ parseContext->recover();
+ type.setArraySize(size);
+ $$.intermAggregate = parseContext->intermediate.makeAggregate(parseContext->intermediate.addSymbol(0, *$2.string, type, $2.line), $2.line);
+
+ if (parseContext->structQualifierErrorCheck($2.line, $1))
+ parseContext->recover();
+
+ if (parseContext->nonInitConstErrorCheck($2.line, *$2.string, $1))
+ parseContext->recover();
+
+ $$.type = $1;
+
+ if (parseContext->arrayTypeErrorCheck($3.line, $1) || parseContext->arrayQualifierErrorCheck($3.line, $1))
+ parseContext->recover();
+ else {
+ int size;
+ if (parseContext->arraySizeErrorCheck($3.line, $4, size))
+ parseContext->recover();
+
+ $1.setArray(true, size);
+ TVariable* variable;
+ if (parseContext->arrayErrorCheck($3.line, *$2.string, $1, variable))
+ parseContext->recover();
+ }
+ }
+ | fully_specified_type IDENTIFIER EQUAL initializer {
+ if (parseContext->structQualifierErrorCheck($2.line, $1))
+ parseContext->recover();
+
+ $$.type = $1;
+
+ TIntermNode* intermNode;
+ if (!parseContext->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) {
+ //
+ // Build intermediate representation
+ //
+ if(intermNode)
+ $$.intermAggregate = parseContext->intermediate.makeAggregate(intermNode, $3.line);
+ else
+ $$.intermAggregate = 0;
+ } else {
+ parseContext->recover();
+ $$.intermAggregate = 0;
+ }
+ }
+ | INVARIANT IDENTIFIER {
+ VERTEX_ONLY("invariant declaration", $1.line);
+ $$.qualifier = EvqInvariantVaryingOut;
+ $$.intermAggregate = 0;
+ }
+
+//
+// Place holder for the pack/unpack languages.
+//
+// | buffer_specifier {
+// $$.intermAggregate = 0;
+// }
+ ;
+
+// Grammar Note: No 'enum', or 'typedef'.
+
+//
+// Place holder for the pack/unpack languages.
+//
+//%type <interm> buffer_declaration
+//%type <interm.type> buffer_specifier input_or_output buffer_declaration_list
+//buffer_specifier
+// : input_or_output LEFT_BRACE buffer_declaration_list RIGHT_BRACE {
+// }
+// ;
+//
+//input_or_output
+// : INPUT {
+// if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "input"))
+// parseContext->recover();
+// UNPACK_ONLY("input", $1.line);
+// $$.qualifier = EvqInput;
+// }
+// | OUTPUT {
+// if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "output"))
+// parseContext->recover();
+// PACK_ONLY("output", $1.line);
+// $$.qualifier = EvqOutput;
+// }
+// ;
+
+//
+// Place holder for the pack/unpack languages.
+//
+//buffer_declaration_list
+// : buffer_declaration {
+// }
+// | buffer_declaration_list buffer_declaration {
+// }
+// ;
+
+//
+// Input/output semantics:
+// float must be 16 or 32 bits
+// float alignment restrictions?
+// check for only one input and only one output
+// sum of bitfields has to be multiple of 32
+//
+
+//
+// Place holder for the pack/unpack languages.
+//
+//buffer_declaration
+// : type_specifier IDENTIFIER COLON constant_expression SEMICOLON {
+// if (parseContext->reservedErrorCheck($2.line, *$2.string, parseContext))
+// parseContext->recover();
+// $$.variable = new TVariable($2.string, $1);
+// if (! parseContext->symbolTable.insert(*$$.variable)) {
+// parseContext->error($2.line, "redefinition", $$.variable->getName().c_str(), "");
+// parseContext->recover();
+// // don't have to delete $$.variable, the pool pop will take care of it
+// }
+// }
+// ;
+
+fully_specified_type
+ : type_specifier {
+ $$ = $1;
+
+ if ($1.array) {
+ if (parseContext->extensionErrorCheck($1.line, "GL_3DL_array_objects")) {
+ parseContext->recover();
+ $1.setArray(false);
+ }
+ }
+ }
+ | type_qualifier type_specifier {
+ if ($2.array && parseContext->extensionErrorCheck($2.line, "GL_3DL_array_objects")) {
+ parseContext->recover();
+ $2.setArray(false);
+ }
+ if ($2.array && parseContext->arrayQualifierErrorCheck($2.line, $1)) {
+ parseContext->recover();
+ $2.setArray(false);
+ }
+
+ if ($1.qualifier == EvqAttribute &&
+ ($2.type == EbtBool || $2.type == EbtInt)) {
+ parseContext->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), "");
+ parseContext->recover();
+ }
+ if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) &&
+ ($2.type == EbtBool || $2.type == EbtInt)) {
+ parseContext->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), "");
+ parseContext->recover();
+ }
+ $$ = $2;
+ $$.qualifier = $1.qualifier;
+ }
+ ;
+
+type_qualifier
+ : CONST_QUAL {
+ $$.setBasic(EbtVoid, EvqConst, $1.line);
+ }
+ | ATTRIBUTE {
+ VERTEX_ONLY("attribute", $1.line);
+ if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "attribute"))
+ parseContext->recover();
+ $$.setBasic(EbtVoid, EvqAttribute, $1.line);
+ }
+ | VARYING {
+ if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "varying"))
+ parseContext->recover();
+ if (parseContext->language == EShLangVertex)
+ $$.setBasic(EbtVoid, EvqVaryingOut, $1.line);
+ else
+ $$.setBasic(EbtVoid, EvqVaryingIn, $1.line);
+ }
+ | INVARIANT VARYING {
+ if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "invariant varying"))
+ parseContext->recover();
+ if (parseContext->language == EShLangVertex)
+ $$.setBasic(EbtVoid, EvqInvariantVaryingOut, $1.line);
+ else
+ $$.setBasic(EbtVoid, EvqInvariantVaryingIn, $1.line);
+ }
+ | UNIFORM {
+ if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "uniform"))
+ parseContext->recover();
+ $$.setBasic(EbtVoid, EvqUniform, $1.line);
+ }
+ ;
+
+type_specifier
+ : type_specifier_no_prec {
+ $$ = $1;
+ }
+ | precision_qualifier type_specifier_no_prec {
+ $$ = $2;
+ $$.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 (parseContext->arrayTypeErrorCheck($2.line, $1))
+ parseContext->recover();
+ else {
+ int size;
+ if (parseContext->arraySizeErrorCheck($2.line, $3, size))
+ parseContext->recover();
+ $$.setArray(true, size);
+ }
+ }
+ ;
+
+type_specifier_nonarray
+ : VOID_TYPE {
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtVoid, qual, $1.line);
+ }
+ | FLOAT_TYPE {
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtFloat, qual, $1.line);
+ }
+ | INT_TYPE {
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtInt, qual, $1.line);
+ }
+ | BOOL_TYPE {
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtBool, qual, $1.line);
+ }
+// | UNSIGNED INT_TYPE {
+// PACK_UNPACK_ONLY("unsigned", $1.line);
+// TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+// $$.setBasic(EbtInt, qual, $1.line);
+// }
+ | VEC2 {
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtFloat, qual, $1.line);
+ $$.setAggregate(2);
+ }
+ | VEC3 {
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtFloat, qual, $1.line);
+ $$.setAggregate(3);
+ }
+ | VEC4 {
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtFloat, qual, $1.line);
+ $$.setAggregate(4);
+ }
+ | BVEC2 {
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtBool, qual, $1.line);
+ $$.setAggregate(2);
+ }
+ | BVEC3 {
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtBool, qual, $1.line);
+ $$.setAggregate(3);
+ }
+ | BVEC4 {
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtBool, qual, $1.line);
+ $$.setAggregate(4);
+ }
+ | IVEC2 {
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtInt, qual, $1.line);
+ $$.setAggregate(2);
+ }
+ | IVEC3 {
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtInt, qual, $1.line);
+ $$.setAggregate(3);
+ }
+ | IVEC4 {
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtInt, qual, $1.line);
+ $$.setAggregate(4);
+ }
+ | MATRIX2 {
+ FRAG_VERT_ONLY("mat2", $1.line);
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtFloat, qual, $1.line);
+ $$.setAggregate(2, true);
+ }
+ | MATRIX3 {
+ FRAG_VERT_ONLY("mat3", $1.line);
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtFloat, qual, $1.line);
+ $$.setAggregate(3, true);
+ }
+ | MATRIX4 {
+ FRAG_VERT_ONLY("mat4", $1.line);
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtFloat, qual, $1.line);
+ $$.setAggregate(4, true);
+ }
+ | SAMPLER2D {
+ FRAG_VERT_ONLY("sampler2D", $1.line);
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtSampler2D, qual, $1.line);
+ }
+ | SAMPLERCUBE {
+ FRAG_VERT_ONLY("samplerCube", $1.line);
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtSamplerCube, qual, $1.line);
+ }
+ | struct_specifier {
+ FRAG_VERT_ONLY("struct", $1.line);
+ $$ = $1;
+ $$.qualifier = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ }
+ | TYPE_NAME {
+ //
+ // This is for user defined type names. The lexical phase looked up the
+ // type.
+ //
+ TType& structure = static_cast<TVariable*>($1.symbol)->getType();
+ TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtStruct, qual, $1.line);
+ $$.userDef = &structure;
+ }
+ ;
+
+struct_specifier
+ : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE {
+ if (parseContext->reservedErrorCheck($2.line, *$2.string))
+ parseContext->recover();
+
+ TType* structure = new TType($4, *$2.string);
+ TVariable* userTypeDef = new TVariable($2.string, *structure, true);
+ if (! parseContext->symbolTable.insert(*userTypeDef)) {
+ parseContext->error($2.line, "redefinition", $2.string->c_str(), "struct");
+ parseContext->recover();
+ }
+ $$.setBasic(EbtStruct, EvqTemporary, $1.line);
+ $$.userDef = structure;
+ }
+ | STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE {
+ TType* structure = new TType($3, TString(""));
+ $$.setBasic(EbtStruct, EvqTemporary, $1.line);
+ $$.userDef = structure;
+ }
+ ;
+
+struct_declaration_list
+ : struct_declaration {
+ $$ = $1;
+ }
+ | struct_declaration_list struct_declaration {
+ $$ = $1;
+ for (unsigned int i = 0; i < $2->size(); ++i) {
+ for (unsigned int j = 0; j < $$->size(); ++j) {
+ if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) {
+ parseContext->error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str());
+ parseContext->recover();
+ }
+ }
+ $$->push_back((*$2)[i]);
+ }
+ }
+ ;
+
+struct_declaration
+ : type_specifier struct_declarator_list SEMICOLON {
+ $$ = $2;
+
+ if (parseContext->voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) {
+ parseContext->recover();
+ }
+ for (unsigned int i = 0; i < $$->size(); ++i) {
+ //
+ // Careful not to replace already known aspects of type, like array-ness
+ //
+ TType* type = (*$$)[i].type;
+ type->setBasicType($1.type);
+ type->setNominalSize($1.size);
+ type->setMatrix($1.matrix);
+
+ // don't allow arrays of arrays
+ if (type->isArray()) {
+ if (parseContext->arrayTypeErrorCheck($1.line, $1))
+ parseContext->recover();
+ }
+ if ($1.array)
+ type->setArraySize($1.arraySize);
+ if ($1.userDef) {
+ type->setStruct($1.userDef->getStruct());
+ type->setTypeName($1.userDef->getTypeName());
+ }
+ }
+ }
+ ;
+
+struct_declarator_list
+ : struct_declarator {
+ $$ = NewPoolTTypeList();
+ $$->push_back($1);
+ }
+ | struct_declarator_list COMMA struct_declarator {
+ $$->push_back($3);
+ }
+ ;
+
+struct_declarator
+ : IDENTIFIER {
+ if (parseContext->reservedErrorCheck($1.line, *$1.string))
+ parseContext->recover();
+
+ $$.type = new TType(EbtVoid, EbpUndefined);
+ $$.line = $1.line;
+ $$.type->setFieldName(*$1.string);
+ }
+ | IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ if (parseContext->reservedErrorCheck($1.line, *$1.string))
+ parseContext->recover();
+
+ $$.type = new TType(EbtVoid, EbpUndefined);
+ $$.line = $1.line;
+ $$.type->setFieldName(*$1.string);
+
+ int size;
+ if (parseContext->arraySizeErrorCheck($2.line, $3, size))
+ parseContext->recover();
+ $$.type->setArraySize(size);
+ }
+ ;
+
+initializer
+ : assignment_expression { $$ = $1; }
+ ;
+
+declaration_statement
+ : declaration { $$ = $1; }
+ ;
+
+statement
+ : compound_statement { $$ = $1; }
+ | simple_statement { $$ = $1; }
+ ;
+
+// Grammar Note: No labeled statements; 'goto' is not supported.
+
+simple_statement
+ : declaration_statement { $$ = $1; }
+ | expression_statement { $$ = $1; }
+ | selection_statement { $$ = $1; }
+ | iteration_statement { $$ = $1; }
+ | jump_statement { $$ = $1; }
+ ;
+
+compound_statement
+ : LEFT_BRACE RIGHT_BRACE { $$ = 0; }
+ | LEFT_BRACE { parseContext->symbolTable.push(); } statement_list { parseContext->symbolTable.pop(); } RIGHT_BRACE {
+ if ($3 != 0)
+ $3->setOp(EOpSequence);
+ $$ = $3;
+ }
+ ;
+
+statement_no_new_scope
+ : compound_statement_no_new_scope { $$ = $1; }
+ | simple_statement { $$ = $1; }
+ ;
+
+compound_statement_no_new_scope
+ // Statement that doesn't create a new scope, for selection_statement, iteration_statement
+ : LEFT_BRACE RIGHT_BRACE {
+ $$ = 0;
+ }
+ | LEFT_BRACE statement_list RIGHT_BRACE {
+ if ($2)
+ $2->setOp(EOpSequence);
+ $$ = $2;
+ }
+ ;
+
+statement_list
+ : statement {
+ $$ = parseContext->intermediate.makeAggregate($1, 0);
+ }
+ | statement_list statement {
+ $$ = parseContext->intermediate.growAggregate($1, $2, 0);
+ }
+ ;
+
+expression_statement
+ : SEMICOLON { $$ = 0; }
+ | expression SEMICOLON { $$ = static_cast<TIntermNode*>($1); }
+ ;
+
+selection_statement
+ : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
+ if (parseContext->boolErrorCheck($1.line, $3))
+ parseContext->recover();
+ $$ = parseContext->intermediate.addSelection($3, $5, $1.line);
+ }
+ ;
+
+selection_rest_statement
+ : statement ELSE statement {
+ $$.node1 = $1;
+ $$.node2 = $3;
+ }
+ | statement {
+ $$.node1 = $1;
+ $$.node2 = 0;
+ }
+ ;
+
+// Grammar Note: No 'switch'. Switch statements not supported.
+
+condition
+ // In 1996 c++ draft, conditions can include single declarations
+ : expression {
+ $$ = $1;
+ if (parseContext->boolErrorCheck($1->getLine(), $1))
+ parseContext->recover();
+ }
+ | fully_specified_type IDENTIFIER EQUAL initializer {
+ TIntermNode* intermNode;
+ if (parseContext->structQualifierErrorCheck($2.line, $1))
+ parseContext->recover();
+ if (parseContext->boolErrorCheck($2.line, $1))
+ parseContext->recover();
+
+ if (!parseContext->executeInitializer($2.line, *$2.string, $1, $4, intermNode))
+ $$ = $4;
+ else {
+ parseContext->recover();
+ $$ = 0;
+ }
+ }
+ ;
+
+iteration_statement
+ : WHILE LEFT_PAREN { parseContext->symbolTable.push(); ++parseContext->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {
+ parseContext->symbolTable.pop();
+ $$ = parseContext->intermediate.addLoop(0, $6, $4, 0, true, $1.line);
+ --parseContext->loopNestingLevel;
+ }
+ | DO { ++parseContext->loopNestingLevel; } statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
+ if (parseContext->boolErrorCheck($8.line, $6))
+ parseContext->recover();
+
+ $$ = parseContext->intermediate.addLoop(0, $3, $6, 0, false, $4.line);
+ --parseContext->loopNestingLevel;
+ }
+ | FOR LEFT_PAREN { parseContext->symbolTable.push(); ++parseContext->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
+ parseContext->symbolTable.pop();
+ $$ = parseContext->intermediate.addLoop($4, $7, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), true, $1.line);
+ --parseContext->loopNestingLevel;
+ }
+ ;
+
+for_init_statement
+ : expression_statement {
+ $$ = $1;
+ }
+ | declaration_statement {
+ $$ = $1;
+ }
+ ;
+
+conditionopt
+ : condition {
+ $$ = $1;
+ }
+ | /* May be null */ {
+ $$ = 0;
+ }
+ ;
+
+for_rest_statement
+ : conditionopt SEMICOLON {
+ $$.node1 = $1;
+ $$.node2 = 0;
+ }
+ | conditionopt SEMICOLON expression {
+ $$.node1 = $1;
+ $$.node2 = $3;
+ }
+ ;
+
+jump_statement
+ : CONTINUE SEMICOLON {
+ if (parseContext->loopNestingLevel <= 0) {
+ parseContext->error($1.line, "continue statement only allowed in loops", "", "");
+ parseContext->recover();
+ }
+ $$ = parseContext->intermediate.addBranch(EOpContinue, $1.line);
+ }
+ | BREAK SEMICOLON {
+ if (parseContext->loopNestingLevel <= 0) {
+ parseContext->error($1.line, "break statement only allowed in loops", "", "");
+ parseContext->recover();
+ }
+ $$ = parseContext->intermediate.addBranch(EOpBreak, $1.line);
+ }
+ | RETURN SEMICOLON {
+ $$ = parseContext->intermediate.addBranch(EOpReturn, $1.line);
+ if (parseContext->currentFunctionType->getBasicType() != EbtVoid) {
+ parseContext->error($1.line, "non-void function must return a value", "return", "");
+ parseContext->recover();
+ }
+ }
+ | RETURN expression SEMICOLON {
+ $$ = parseContext->intermediate.addBranch(EOpReturn, $2, $1.line);
+ parseContext->functionReturnsValue = true;
+ if (parseContext->currentFunctionType->getBasicType() == EbtVoid) {
+ parseContext->error($1.line, "void function cannot return a value", "return", "");
+ parseContext->recover();
+ } else if (*(parseContext->currentFunctionType) != $2->getType()) {
+ parseContext->error($1.line, "function return is not matching type:", "return", "");
+ parseContext->recover();
+ }
+ }
+ | DISCARD SEMICOLON {
+ FRAG_ONLY("discard", $1.line);
+ $$ = parseContext->intermediate.addBranch(EOpKill, $1.line);
+ }
+ ;
+
+// Grammar Note: No 'goto'. Gotos are not supported.
+
+translation_unit
+ : external_declaration {
+ $$ = $1;
+ parseContext->treeRoot = $$;
+ }
+ | translation_unit external_declaration {
+ $$ = parseContext->intermediate.growAggregate($1, $2, 0);
+ parseContext->treeRoot = $$;
+ }
+ ;
+
+external_declaration
+ : function_definition {
+ $$ = $1;
+ }
+ | declaration {
+ $$ = $1;
+ }
+ ;
+
+function_definition
+ : function_prototype {
+ TFunction& function = *($1.function);
+ TFunction* prevDec = static_cast<TFunction*>(parseContext->symbolTable.find(function.getMangledName()));
+ //
+ // Note: 'prevDec' could be 'function' if this is the first time we've seen function
+ // as it would have just been put in the symbol table. Otherwise, we're looking up
+ // an earlier occurance.
+ //
+ if (prevDec->isDefined()) {
+ //
+ // Then this function already has a body.
+ //
+ parseContext->error($1.line, "function already has a body", function.getName().c_str(), "");
+ parseContext->recover();
+ }
+ prevDec->setDefined();
+
+ //
+ // Raise error message if main function takes any parameters or return anything other than void
+ //
+ if (function.getName() == "main") {
+ if (function.getParamCount() > 0) {
+ parseContext->error($1.line, "function cannot take any parameter(s)", function.getName().c_str(), "");
+ parseContext->recover();
+ }
+ if (function.getReturnType().getBasicType() != EbtVoid) {
+ parseContext->error($1.line, "", function.getReturnType().getBasicString(), "main function cannot return a value");
+ parseContext->recover();
+ }
+ }
+
+ //
+ // New symbol table scope for body of function plus its arguments
+ //
+ parseContext->symbolTable.push();
+
+ //
+ // Remember the return type for later checking for RETURN statements.
+ //
+ parseContext->currentFunctionType = &(prevDec->getReturnType());
+ parseContext->functionReturnsValue = false;
+
+ //
+ // Insert parameters into the symbol table.
+ // If the parameter has no name, it's not an error, just don't insert it
+ // (could be used for unused args).
+ //
+ // Also, accumulate the list of parameters into the HIL, so lower level code
+ // knows where to find parameters.
+ //
+ TIntermAggregate* paramNodes = new TIntermAggregate;
+ for (int i = 0; i < function.getParamCount(); i++) {
+ TParameter& param = function[i];
+ if (param.name != 0) {
+ TVariable *variable = new TVariable(param.name, *param.type);
+ //
+ // Insert the parameters with name in the symbol table.
+ //
+ if (! parseContext->symbolTable.insert(*variable)) {
+ parseContext->error($1.line, "redefinition", variable->getName().c_str(), "");
+ parseContext->recover();
+ delete variable;
+ }
+ //
+ // Transfer ownership of name pointer to symbol table.
+ //
+ param.name = 0;
+
+ //
+ // Add the parameter to the HIL
+ //
+ paramNodes = parseContext->intermediate.growAggregate(
+ paramNodes,
+ parseContext->intermediate.addSymbol(variable->getUniqueId(),
+ variable->getName(),
+ variable->getType(), $1.line),
+ $1.line);
+ } else {
+ paramNodes = parseContext->intermediate.growAggregate(paramNodes, parseContext->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
+ }
+ }
+ parseContext->intermediate.setAggregateOperator(paramNodes, EOpParameters, $1.line);
+ $1.intermAggregate = paramNodes;
+ parseContext->loopNestingLevel = 0;
+ }
+ compound_statement_no_new_scope {
+ //?? Check that all paths return a value if return type != void ?
+ // May be best done as post process phase on intermediate code
+ if (parseContext->currentFunctionType->getBasicType() != EbtVoid && ! parseContext->functionReturnsValue) {
+ parseContext->error($1.line, "function does not return a value:", "", $1.function->getName().c_str());
+ parseContext->recover();
+ }
+ parseContext->symbolTable.pop();
+ $$ = parseContext->intermediate.growAggregate($1.intermAggregate, $3, 0);
+ parseContext->intermediate.setAggregateOperator($$, EOpFunction, $1.line);
+ $$->getAsAggregate()->setName($1.function->getMangledName().c_str());
+ $$->getAsAggregate()->setType($1.function->getReturnType());
+
+ // store the pragma information for debug and optimize and other vendor specific
+ // information. This information can be queried from the parse tree
+ $$->getAsAggregate()->setOptimize(parseContext->contextPragma.optimize);
+ $$->getAsAggregate()->setDebug(parseContext->contextPragma.debug);
+ $$->getAsAggregate()->addToPragmaTable(parseContext->contextPragma.pragmaTable);
+ }
+ ;
+
+%%
diff --git a/Source/ThirdParty/ANGLE/src/compiler/intermOut.cpp b/Source/ThirdParty/ANGLE/src/compiler/intermOut.cpp
new file mode 100644
index 0000000..db042dd
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/intermOut.cpp
@@ -0,0 +1,417 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/localintermediate.h"
+
+//
+// Two purposes:
+// 1. Show an example of how to iterate tree. Functions can
+// also directly call Traverse() on children themselves to
+// have finer grained control over the process than shown here.
+// See the last function for how to get started.
+// 2. Print out a text based description of the tree.
+//
+
+//
+// Use this class to carry along data from node to node in
+// the traversal
+//
+class TOutputTraverser : public TIntermTraverser {
+public:
+ TOutputTraverser(TInfoSink& i) : infoSink(i) { }
+ TInfoSink& infoSink;
+
+protected:
+ void visitSymbol(TIntermSymbol*);
+ void visitConstantUnion(TIntermConstantUnion*);
+ bool visitBinary(Visit visit, TIntermBinary*);
+ bool visitUnary(Visit visit, TIntermUnary*);
+ bool visitSelection(Visit visit, TIntermSelection*);
+ bool visitAggregate(Visit visit, TIntermAggregate*);
+ bool visitLoop(Visit visit, TIntermLoop*);
+ bool visitBranch(Visit visit, TIntermBranch*);
+};
+
+TString TType::getCompleteString() const
+{
+ 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(TInfoSink& infoSink, TIntermNode* node, const int depth)
+{
+ int i;
+
+ infoSink.debug.location(node->getLine());
+
+ for (i = 0; i < depth; ++i)
+ infoSink.debug << " ";
+}
+
+//
+// The rest of the file are the traversal functions. The last one
+// is the one that starts the traversal.
+//
+// Return true from interior nodes to have the external traversal
+// continue on to children. If you process children yourself,
+// return false.
+//
+
+void TOutputTraverser::visitSymbol(TIntermSymbol* node)
+{
+ OutputTreeText(infoSink, node, depth);
+
+ infoSink.debug << "'" << node->getSymbol() << "' ";
+ infoSink.debug << "(" << node->getCompleteString() << ")\n";
+}
+
+bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node)
+{
+ TInfoSink& out = infoSink;
+
+ OutputTreeText(out, node, depth);
+
+ switch (node->getOp()) {
+ case EOpAssign: out.debug << "move second child to first child"; break;
+ case EOpInitialize: out.debug << "initialize first child with second child"; break;
+ case EOpAddAssign: out.debug << "add second child into first child"; break;
+ case EOpSubAssign: out.debug << "subtract second child into first child"; break;
+ case EOpMulAssign: out.debug << "multiply second child into first child"; break;
+ case EOpVectorTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break;
+ case EOpVectorTimesScalarAssign: out.debug << "vector scale second child into first child"; break;
+ case EOpMatrixTimesScalarAssign: out.debug << "matrix scale second child into first child"; break;
+ case EOpMatrixTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break;
+ case EOpDivAssign: out.debug << "divide second child into first child"; break;
+ case EOpIndexDirect: out.debug << "direct index"; break;
+ case EOpIndexIndirect: out.debug << "indirect index"; break;
+ case EOpIndexDirectStruct: out.debug << "direct index for structure"; break;
+ case EOpVectorSwizzle: out.debug << "vector swizzle"; break;
+
+ case EOpAdd: out.debug << "add"; break;
+ case EOpSub: out.debug << "subtract"; break;
+ case EOpMul: out.debug << "component-wise multiply"; break;
+ case EOpDiv: out.debug << "divide"; break;
+ case EOpEqual: out.debug << "Compare Equal"; break;
+ case EOpNotEqual: out.debug << "Compare Not Equal"; break;
+ case EOpLessThan: out.debug << "Compare Less Than"; break;
+ case EOpGreaterThan: out.debug << "Compare Greater Than"; break;
+ case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break;
+ case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
+
+ case EOpVectorTimesScalar: out.debug << "vector-scale"; break;
+ case EOpVectorTimesMatrix: out.debug << "vector-times-matrix"; break;
+ case EOpMatrixTimesVector: out.debug << "matrix-times-vector"; break;
+ case EOpMatrixTimesScalar: out.debug << "matrix-scale"; break;
+ case EOpMatrixTimesMatrix: out.debug << "matrix-multiply"; break;
+
+ case EOpLogicalOr: out.debug << "logical-or"; break;
+ case EOpLogicalXor: out.debug << "logical-xor"; break;
+ case EOpLogicalAnd: out.debug << "logical-and"; break;
+ default: out.debug << "<unknown op>";
+ }
+
+ out.debug << " (" << node->getCompleteString() << ")";
+
+ out.debug << "\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node)
+{
+ TInfoSink& out = infoSink;
+
+ OutputTreeText(out, node, depth);
+
+ switch (node->getOp()) {
+ case EOpNegative: out.debug << "Negate value"; break;
+ case EOpVectorLogicalNot:
+ case EOpLogicalNot: out.debug << "Negate conditional"; break;
+
+ case EOpPostIncrement: out.debug << "Post-Increment"; break;
+ case EOpPostDecrement: out.debug << "Post-Decrement"; break;
+ case EOpPreIncrement: out.debug << "Pre-Increment"; break;
+ case EOpPreDecrement: out.debug << "Pre-Decrement"; break;
+
+ case EOpConvIntToBool: out.debug << "Convert int to bool"; break;
+ case EOpConvFloatToBool:out.debug << "Convert float to bool";break;
+ case EOpConvBoolToFloat:out.debug << "Convert bool to float";break;
+ case EOpConvIntToFloat: out.debug << "Convert int to float"; break;
+ case EOpConvFloatToInt: out.debug << "Convert float to int"; break;
+ case EOpConvBoolToInt: out.debug << "Convert bool to int"; break;
+
+ case EOpRadians: out.debug << "radians"; break;
+ case EOpDegrees: out.debug << "degrees"; break;
+ case EOpSin: out.debug << "sine"; break;
+ case EOpCos: out.debug << "cosine"; break;
+ case EOpTan: out.debug << "tangent"; break;
+ case EOpAsin: out.debug << "arc sine"; break;
+ case EOpAcos: out.debug << "arc cosine"; break;
+ case EOpAtan: out.debug << "arc tangent"; break;
+
+ case EOpExp: out.debug << "exp"; break;
+ case EOpLog: out.debug << "log"; break;
+ case EOpExp2: out.debug << "exp2"; break;
+ case EOpLog2: out.debug << "log2"; break;
+ case EOpSqrt: out.debug << "sqrt"; break;
+ case EOpInverseSqrt: out.debug << "inverse sqrt"; break;
+
+ case EOpAbs: out.debug << "Absolute value"; break;
+ case EOpSign: out.debug << "Sign"; break;
+ case EOpFloor: out.debug << "Floor"; break;
+ case EOpCeil: out.debug << "Ceiling"; break;
+ case EOpFract: out.debug << "Fraction"; break;
+
+ case EOpLength: out.debug << "length"; break;
+ case EOpNormalize: out.debug << "normalize"; break;
+ // case EOpDPdx: out.debug << "dPdx"; break;
+ // case EOpDPdy: out.debug << "dPdy"; break;
+ // case EOpFwidth: out.debug << "fwidth"; break;
+
+ case EOpAny: out.debug << "any"; break;
+ case EOpAll: out.debug << "all"; break;
+
+ default: out.debug.message(EPrefixError, "Bad unary op");
+ }
+
+ out.debug << " (" << node->getCompleteString() << ")";
+
+ out.debug << "\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+ TInfoSink& out = infoSink;
+
+ if (node->getOp() == EOpNull) {
+ out.debug.message(EPrefixError, "node is still EOpNull!");
+ return true;
+ }
+
+ OutputTreeText(out, node, depth);
+
+ switch (node->getOp()) {
+ case EOpSequence: out.debug << "Sequence\n"; return true;
+ case EOpComma: out.debug << "Comma\n"; return true;
+ case EOpFunction: out.debug << "Function Definition: " << node->getName(); break;
+ case EOpFunctionCall: out.debug << "Function Call: " << node->getName(); break;
+ case EOpParameters: out.debug << "Function Parameters: "; break;
+
+ case EOpConstructFloat: out.debug << "Construct float"; break;
+ case EOpConstructVec2: out.debug << "Construct vec2"; break;
+ case EOpConstructVec3: out.debug << "Construct vec3"; break;
+ case EOpConstructVec4: out.debug << "Construct vec4"; break;
+ case EOpConstructBool: out.debug << "Construct bool"; break;
+ case EOpConstructBVec2: out.debug << "Construct bvec2"; break;
+ case EOpConstructBVec3: out.debug << "Construct bvec3"; break;
+ case EOpConstructBVec4: out.debug << "Construct bvec4"; break;
+ case EOpConstructInt: out.debug << "Construct int"; break;
+ case EOpConstructIVec2: out.debug << "Construct ivec2"; break;
+ case EOpConstructIVec3: out.debug << "Construct ivec3"; break;
+ case EOpConstructIVec4: out.debug << "Construct ivec4"; break;
+ case EOpConstructMat2: out.debug << "Construct mat2"; break;
+ case EOpConstructMat3: out.debug << "Construct mat3"; break;
+ case EOpConstructMat4: out.debug << "Construct mat4"; break;
+ case EOpConstructStruct: out.debug << "Construct structure"; break;
+
+ case EOpLessThan: out.debug << "Compare Less Than"; break;
+ case EOpGreaterThan: out.debug << "Compare Greater Than"; break;
+ case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break;
+ case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
+ case EOpVectorEqual: out.debug << "Equal"; break;
+ case EOpVectorNotEqual: out.debug << "NotEqual"; break;
+
+ case EOpMod: out.debug << "mod"; break;
+ case EOpPow: out.debug << "pow"; break;
+
+ case EOpAtan: out.debug << "arc tangent"; break;
+
+ case EOpMin: out.debug << "min"; break;
+ case EOpMax: out.debug << "max"; break;
+ case EOpClamp: out.debug << "clamp"; break;
+ case EOpMix: out.debug << "mix"; break;
+ case EOpStep: out.debug << "step"; break;
+ case EOpSmoothStep: out.debug << "smoothstep"; break;
+
+ case EOpDistance: out.debug << "distance"; break;
+ case EOpDot: out.debug << "dot-product"; break;
+ case EOpCross: out.debug << "cross-product"; break;
+ case EOpFaceForward: out.debug << "face-forward"; break;
+ case EOpReflect: out.debug << "reflect"; break;
+ case EOpRefract: out.debug << "refract"; break;
+ case EOpMul: out.debug << "component-wise multiply"; break;
+
+ default: out.debug.message(EPrefixError, "Bad aggregation op");
+ }
+
+ if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
+ out.debug << " (" << node->getCompleteString() << ")";
+
+ out.debug << "\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node)
+{
+ TInfoSink& out = infoSink;
+
+ OutputTreeText(out, node, depth);
+
+ out.debug << "Test condition and select";
+ out.debug << " (" << node->getCompleteString() << ")\n";
+
+ ++depth;
+
+ OutputTreeText(infoSink, node, depth);
+ out.debug << "Condition\n";
+ node->getCondition()->traverse(this);
+
+ OutputTreeText(infoSink, node, depth);
+ if (node->getTrueBlock()) {
+ out.debug << "true case\n";
+ node->getTrueBlock()->traverse(this);
+ } else
+ out.debug << "true case is null\n";
+
+ if (node->getFalseBlock()) {
+ OutputTreeText(infoSink, node, depth);
+ out.debug << "false case\n";
+ node->getFalseBlock()->traverse(this);
+ }
+
+ --depth;
+
+ return false;
+}
+
+void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
+{
+ TInfoSink& out = infoSink;
+
+ int size = node->getType().getObjectSize();
+
+ for (int i = 0; i < size; i++) {
+ OutputTreeText(out, node, depth);
+ switch (node->getUnionArrayPointer()[i].getType()) {
+ case EbtBool:
+ if (node->getUnionArrayPointer()[i].getBConst())
+ out.debug << "true";
+ else
+ out.debug << "false";
+
+ out.debug << " (" << "const bool" << ")";
+ out.debug << "\n";
+ break;
+ case EbtFloat:
+ out.debug << node->getUnionArrayPointer()[i].getFConst();
+ out.debug << " (const float)\n";
+ break;
+ case EbtInt:
+ out.debug << node->getUnionArrayPointer()[i].getIConst();
+ out.debug << " (const int)\n";
+ break;
+ default:
+ out.info.message(EPrefixInternalError, "Unknown constant", node->getLine());
+ break;
+ }
+ }
+}
+
+bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node)
+{
+ TInfoSink& out = infoSink;
+
+ OutputTreeText(out, node, depth);
+
+ out.debug << "Loop with condition ";
+ if (! node->testFirst())
+ out.debug << "not ";
+ out.debug << "tested first\n";
+
+ ++depth;
+
+ OutputTreeText(infoSink, node, depth);
+ if (node->getTest()) {
+ out.debug << "Loop Condition\n";
+ node->getTest()->traverse(this);
+ } else
+ out.debug << "No loop condition\n";
+
+ OutputTreeText(infoSink, node, depth);
+ if (node->getBody()) {
+ out.debug << "Loop Body\n";
+ node->getBody()->traverse(this);
+ } else
+ out.debug << "No loop body\n";
+
+ if (node->getTerminal()) {
+ OutputTreeText(infoSink, node, depth);
+ out.debug << "Loop Terminal Expression\n";
+ node->getTerminal()->traverse(this);
+ }
+
+ --depth;
+
+ return false;
+}
+
+bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node)
+{
+ TInfoSink& out = infoSink;
+
+ OutputTreeText(out, node, depth);
+
+ switch (node->getFlowOp()) {
+ case EOpKill: out.debug << "Branch: Kill"; break;
+ case EOpBreak: out.debug << "Branch: Break"; break;
+ case EOpContinue: out.debug << "Branch: Continue"; break;
+ case EOpReturn: out.debug << "Branch: Return"; break;
+ default: out.debug << "Branch: Unknown Branch"; break;
+ }
+
+ if (node->getExpression()) {
+ out.debug << " with expression\n";
+ ++depth;
+ node->getExpression()->traverse(this);
+ --depth;
+ } else
+ out.debug << "\n";
+
+ return false;
+}
+
+//
+// This function is the one to call externally to start the traversal.
+// Individual functions can be initialized to 0 to skip processing of that
+// type of node. It's children will still be processed.
+//
+void TIntermediate::outputTree(TIntermNode* root)
+{
+ if (root == 0)
+ return;
+
+ TOutputTraverser it(infoSink);
+
+ root->traverse(&it);
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/intermediate.h b/Source/ThirdParty/ANGLE/src/compiler/intermediate.h
new file mode 100644
index 0000000..d262905
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/intermediate.h
@@ -0,0 +1,517 @@
+//
+// 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,
+
+ //EOpDPdx, // Fragment only, OES_standard_derivatives extension
+ //EOpDPdy, // 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,
+};
+
+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.
+//
+class TIntermLoop : public TIntermNode {
+public:
+ TIntermLoop(TIntermNode *init, TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) :
+ init(init),
+ body(aBody),
+ test(aTest),
+ terminal(aTerminal),
+ first(testFirst) { }
+
+ virtual TIntermLoop* getAsLoopNode() { return this; }
+ virtual void traverse(TIntermTraverser*);
+
+ TIntermNode *getInit() { return init; }
+ TIntermNode *getBody() { return body; }
+ TIntermTyped *getTest() { return test; }
+ TIntermTyped *getTerminal() { return terminal; }
+ bool testFirst() { return first; }
+
+protected:
+ TIntermNode *init;
+ TIntermNode *body; // code to loop over
+ TIntermTyped *test; // exit condition associated with loop, could be 0 for 'for' loops
+ TIntermTyped *terminal; // exists for for-loops
+ bool first; // true for while and for, not for do-while
+};
+
+//
+// Handle break, continue, return, and kill.
+//
+class TIntermBranch : public TIntermNode {
+public:
+ TIntermBranch(TOperator op, TIntermTyped* e) :
+ flowOp(op),
+ expression(e) { }
+
+ virtual void traverse(TIntermTraverser*);
+
+ TOperator getFlowOp() { return flowOp; }
+ TIntermTyped* getExpression() { return expression; }
+
+protected:
+ TOperator flowOp;
+ TIntermTyped* expression; // non-zero except for "return exp;" statements
+};
+
+//
+// Nodes that correspond to symbols or constants in the source code.
+//
+class TIntermSymbol : public TIntermTyped {
+public:
+ // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
+ // per process globalpoolallocator, then it causes increased memory usage per compile
+ // it is essential to use "symbol = sym" to assign to symbol
+ TIntermSymbol(int i, const TString& sym, const TType& t) :
+ TIntermTyped(t), id(i) { symbol = sym;}
+
+ int getId() const { return id; }
+ const TString& getSymbol() const { return symbol; }
+
+ virtual void traverse(TIntermTraverser*);
+ virtual TIntermSymbol* getAsSymbolNode() { return this; }
+
+protected:
+ int id;
+ TString symbol;
+};
+
+class TIntermConstantUnion : public TIntermTyped {
+public:
+ TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
+
+ ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
+ void setUnionArrayPointer(ConstantUnion *c) { unionArrayPointer = c; }
+
+ virtual TIntermConstantUnion* getAsConstantUnion() { return this; }
+ virtual void traverse(TIntermTraverser*);
+
+ TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
+
+protected:
+ ConstantUnion *unionArrayPointer;
+};
+
+//
+// Intermediate class for node types that hold operators.
+//
+class TIntermOperator : public TIntermTyped {
+public:
+ TOperator getOp() const { return op; }
+ void setOp(TOperator o) { op = o; }
+
+ bool modifiesState() const;
+ bool isConstructor() const;
+
+protected:
+ TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
+ TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}
+ TOperator op;
+};
+
+//
+// Nodes for all the basic binary math operators.
+//
+class TIntermBinary : public TIntermOperator {
+public:
+ TIntermBinary(TOperator o) : TIntermOperator(o) {}
+
+ virtual TIntermBinary* getAsBinaryNode() { return this; }
+ virtual void traverse(TIntermTraverser*);
+
+ void setLeft(TIntermTyped* n) { left = n; }
+ void setRight(TIntermTyped* n) { right = n; }
+ TIntermTyped* getLeft() const { return left; }
+ TIntermTyped* getRight() const { return right; }
+ bool promote(TInfoSink&);
+
+protected:
+ TIntermTyped* left;
+ TIntermTyped* right;
+};
+
+//
+// Nodes for unary math operators.
+//
+class TIntermUnary : public TIntermOperator {
+public:
+ TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {}
+ TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {}
+
+ virtual void traverse(TIntermTraverser*);
+ virtual TIntermUnary* getAsUnaryNode() { return this; }
+
+ void setOperand(TIntermTyped* o) { operand = o; }
+ TIntermTyped* getOperand() { return operand; }
+ bool promote(TInfoSink&);
+
+protected:
+ TIntermTyped* operand;
+};
+
+typedef TVector<TIntermNode*> TIntermSequence;
+typedef TVector<int> TQualifierList;
+//
+// Nodes that operate on an arbitrary sized set of children.
+//
+class TIntermAggregate : public TIntermOperator {
+public:
+ TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0) { }
+ TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { }
+ ~TIntermAggregate() { delete pragmaTable; }
+
+ 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() { return userDefined; }
+ TQualifierList& getQualifier() { return qualifier; }
+ void setOptimize(bool o) { optimize = o; }
+ bool getOptimize() { return optimize; }
+ void setDebug(bool d) { debug = d; }
+ bool getDebug() { return debug; }
+ void addToPragmaTable(const TPragmaTable& pTable);
+ const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
+
+protected:
+ TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
+ TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
+ TIntermSequence sequence;
+ TQualifierList qualifier;
+ TString name;
+ bool userDefined; // used for user defined function names
+ bool optimize;
+ bool debug;
+ TPragmaTable *pragmaTable;
+};
+
+//
+// For if tests. Simplified since there is no switch statement.
+//
+class TIntermSelection : public TIntermTyped {
+public:
+ TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
+ TIntermTyped(TType(EbtVoid, 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 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/Source/ThirdParty/ANGLE/src/compiler/localintermediate.h b/Source/ThirdParty/ANGLE/src/compiler/localintermediate.h
new file mode 100644
index 0000000..5fd4c69
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/localintermediate.h
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _LOCAL_INTERMEDIATE_INCLUDED_
+#define _LOCAL_INTERMEDIATE_INCLUDED_
+
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/intermediate.h"
+#include "compiler/SymbolTable.h"
+
+struct TVectorFields {
+ int offsets[4];
+ int num;
+};
+
+//
+// Set of helper functions to help parse and build the tree.
+//
+class TInfoSink;
+class TIntermediate {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+ TIntermediate(TInfoSink& i) : infoSink(i) { }
+ TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
+ TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
+ TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, TSymbolTable&);
+ TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
+ TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
+ TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, TSourceLoc, TSymbolTable&);
+ TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc);
+ TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc);
+ TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, TSourceLoc);
+ TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, TSourceLoc);
+ TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc);
+ TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc);
+ TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, TSourceLoc);
+ TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
+ bool parseConstTree(TSourceLoc, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false);
+ TIntermNode* addLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, TSourceLoc);
+ TIntermBranch* addBranch(TOperator, TSourceLoc);
+ TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc);
+ TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc);
+ bool postProcess(TIntermNode*, EShLanguage);
+ void remove(TIntermNode*);
+ void outputTree(TIntermNode*);
+
+protected:
+ TInfoSink& infoSink;
+
+private:
+ void operator=(TIntermediate&); // prevent assignments
+};
+
+#endif // _LOCAL_INTERMEDIATE_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/osinclude.h b/Source/ThirdParty/ANGLE/src/compiler/osinclude.h
new file mode 100644
index 0000000..d887914
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/osinclude.h
@@ -0,0 +1,62 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef __OSINCLUDE_H
+#define __OSINCLUDE_H
+
+//
+// This file contains contains the window's specific datatypes and
+// declares any windows specific functions.
+//
+
+#if defined(_WIN32) || defined(_WIN64)
+#define ANGLE_OS_WIN
+#elif defined(__APPLE__) || defined(__linux__) || \
+ defined(__FreeBSD__) || defined(__OpenBSD__) || \
+ defined(__sun)
+#define ANGLE_OS_POSIX
+#else
+#error Unsupported platform.
+#endif
+
+#if defined(ANGLE_OS_WIN)
+#define STRICT
+#define VC_EXTRALEAN 1
+#include <windows.h>
+#elif defined(ANGLE_OS_POSIX)
+#include <pthread.h>
+#include <semaphore.h>
+#include <errno.h>
+#endif // ANGLE_OS_WIN
+
+#include "compiler/debug.h"
+
+//
+// Thread Local Storage Operations
+//
+#if defined(ANGLE_OS_WIN)
+typedef DWORD OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES)
+#elif defined(ANGLE_OS_POSIX)
+typedef unsigned int OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX 0xFFFFFFFF
+#endif // ANGLE_OS_WIN
+
+OS_TLSIndex OS_AllocTLSIndex();
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue);
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex);
+
+inline void* OS_GetTLSValue(OS_TLSIndex nIndex)
+{
+ assert(nIndex != OS_INVALID_TLS_INDEX);
+#if defined(ANGLE_OS_WIN)
+ return TlsGetValue(nIndex);
+#elif defined(ANGLE_OS_POSIX)
+ return pthread_getspecific(nIndex);
+#endif // ANGLE_OS_WIN
+}
+
+#endif // __OSINCLUDE_H
diff --git a/Source/ThirdParty/ANGLE/src/compiler/ossource_posix.cpp b/Source/ThirdParty/ANGLE/src/compiler/ossource_posix.cpp
new file mode 100644
index 0000000..1e1e699
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/ossource_posix.cpp
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// This file contains the posix specific functions
+//
+#include "compiler/osinclude.h"
+
+#if !defined(ANGLE_OS_POSIX)
+#error Trying to build a posix specific file in a non-posix build.
+#endif
+
+//
+// Thread Local Storage Operations
+//
+OS_TLSIndex OS_AllocTLSIndex()
+{
+ pthread_key_t pPoolIndex;
+
+ //
+ // Create global pool key.
+ //
+ if ((pthread_key_create(&pPoolIndex, NULL)) != 0) {
+ assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
+ return false;
+ }
+ else {
+ return pPoolIndex;
+ }
+}
+
+
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
+{
+ if (nIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+ return false;
+ }
+
+ if (pthread_setspecific(nIndex, lpvValue) == 0)
+ return true;
+ else
+ return false;
+}
+
+
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
+{
+ if (nIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+ return false;
+ }
+
+ //
+ // Delete the global pool key.
+ //
+ if (pthread_key_delete(nIndex) == 0)
+ return true;
+ else
+ return false;
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/ossource_win.cpp b/Source/ThirdParty/ANGLE/src/compiler/ossource_win.cpp
new file mode 100644
index 0000000..89922fe
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/ossource_win.cpp
@@ -0,0 +1,57 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/osinclude.h"
+//
+// This file contains contains the window's specific functions
+//
+
+#if !defined(ANGLE_OS_WIN)
+#error Trying to build a windows specific file in a non windows build.
+#endif
+
+
+//
+// Thread Local Storage Operations
+//
+OS_TLSIndex OS_AllocTLSIndex()
+{
+ DWORD dwIndex = TlsAlloc();
+ if (dwIndex == TLS_OUT_OF_INDEXES) {
+ assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
+ return OS_INVALID_TLS_INDEX;
+ }
+
+ return dwIndex;
+}
+
+
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
+{
+ if (nIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+ return false;
+ }
+
+ if (TlsSetValue(nIndex, lpvValue))
+ return true;
+ else
+ return false;
+}
+
+
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
+{
+ if (nIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+ return false;
+ }
+
+ if (TlsFree(nIndex))
+ return true;
+ else
+ return false;
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/parseConst.cpp b/Source/ThirdParty/ANGLE/src/compiler/parseConst.cpp
new file mode 100644
index 0000000..9a8a50c
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/parseConst.cpp
@@ -0,0 +1,238 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/ParseHelper.h"
+
+//
+// Use this class to carry along data from node to node in
+// the traversal
+//
+class TConstTraverser : public TIntermTraverser {
+public:
+ TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t)
+ : error(false),
+ index(0),
+ unionArray(cUnion),
+ type(t),
+ constructorType(constructType),
+ singleConstantParam(singleConstParam),
+ infoSink(sink),
+ symbolTable(symTable),
+ size(0),
+ isMatrix(false),
+ matrixSize(0) {
+ }
+
+ bool error;
+
+protected:
+ void visitSymbol(TIntermSymbol*);
+ void visitConstantUnion(TIntermConstantUnion*);
+ bool visitBinary(Visit visit, TIntermBinary*);
+ bool visitUnary(Visit visit, TIntermUnary*);
+ bool visitSelection(Visit visit, TIntermSelection*);
+ bool visitAggregate(Visit visit, TIntermAggregate*);
+ bool visitLoop(Visit visit, TIntermLoop*);
+ bool visitBranch(Visit visit, TIntermBranch*);
+
+ int index;
+ ConstantUnion *unionArray;
+ TType type;
+ TOperator constructorType;
+ bool singleConstantParam;
+ TInfoSink& infoSink;
+ TSymbolTable& symbolTable;
+ int size; // size of the constructor ( 4 for vec4)
+ bool isMatrix;
+ int matrixSize; // dimension of the matrix (nominal size and not the instance size)
+};
+
+//
+// The rest of the file are the traversal functions. The last one
+// is the one that starts the traversal.
+//
+// Return true from interior nodes to have the external traversal
+// continue on to children. If you process children yourself,
+// return false.
+//
+
+void TConstTraverser::visitSymbol(TIntermSymbol* node)
+{
+ infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
+ return;
+
+}
+
+bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
+{
+ TQualifier qualifier = node->getType().getQualifier();
+
+ if (qualifier != EvqConst) {
+ TString buf;
+ buf.append("'constructor' : assigning non-constant to ");
+ buf.append(type.getCompleteString());
+ infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
+ error = true;
+ return false;
+ }
+
+ infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
+
+ return false;
+}
+
+bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
+{
+ TString buf;
+ buf.append("'constructor' : assigning non-constant to ");
+ buf.append(type.getCompleteString());
+ infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
+ error = true;
+ return false;
+}
+
+bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+ if (!node->isConstructor() && node->getOp() != EOpComma) {
+ TString buf;
+ buf.append("'constructor' : assigning non-constant to ");
+ buf.append(type.getCompleteString());
+ infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
+ error = true;
+ return false;
+ }
+
+ if (node->getSequence().size() == 0) {
+ error = true;
+ return false;
+ }
+
+ bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
+ if (flag)
+ {
+ singleConstantParam = true;
+ constructorType = node->getOp();
+ size = node->getType().getObjectSize();
+
+ if (node->getType().isMatrix()) {
+ isMatrix = true;
+ matrixSize = node->getType().getNominalSize();
+ }
+ }
+
+ for (TIntermSequence::iterator p = node->getSequence().begin();
+ p != node->getSequence().end(); p++) {
+
+ if (node->getOp() == EOpComma)
+ index = 0;
+
+ (*p)->traverse(this);
+ }
+ if (flag)
+ {
+ singleConstantParam = false;
+ constructorType = EOpNull;
+ size = 0;
+ isMatrix = false;
+ matrixSize = 0;
+ }
+ return false;
+}
+
+bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
+{
+ infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
+ error = true;
+ return false;
+}
+
+void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
+{
+ ConstantUnion* leftUnionArray = unionArray;
+ int instanceSize = type.getObjectSize();
+
+ if (index >= instanceSize)
+ return;
+
+ if (!singleConstantParam) {
+ int size = node->getType().getObjectSize();
+
+ ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+ for (int i=0; i < size; i++) {
+ if (index >= instanceSize)
+ return;
+ leftUnionArray[index] = rightUnionArray[i];
+
+ (index)++;
+ }
+ } else {
+ int totalSize = index + size;
+ ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+ if (!isMatrix) {
+ int count = 0;
+ for (int i = index; i < totalSize; i++) {
+ if (i >= instanceSize)
+ return;
+
+ leftUnionArray[i] = rightUnionArray[count];
+
+ (index)++;
+
+ if (node->getType().getObjectSize() > 1)
+ count++;
+ }
+ } else { // for matrix constructors
+ int count = 0;
+ int element = index;
+ for (int i = index; i < totalSize; i++) {
+ if (i >= instanceSize)
+ return;
+ if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 )
+ leftUnionArray[i] = rightUnionArray[count];
+ else
+ leftUnionArray[i].setFConst(0.0f);
+
+ (index)++;
+
+ if (node->getType().getObjectSize() > 1)
+ count++;
+ }
+ }
+ }
+}
+
+bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
+{
+ infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
+ error = true;
+ return false;
+}
+
+bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
+{
+ infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
+ error = true;
+ return false;
+}
+
+//
+// This function is the one to call externally to start the traversal.
+// Individual functions can be initialized to 0 to skip processing of that
+// type of node. It's children will still be processed.
+//
+bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
+{
+ if (root == 0)
+ return false;
+
+ TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t);
+
+ root->traverse(&it);
+ if (it.error)
+ return true;
+ else
+ return false;
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/atom.c b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/atom.c
new file mode 100644
index 0000000..c5636b7
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/atom.c
@@ -0,0 +1,735 @@
+/****************************************************************************\
+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 "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);
+ if (stable->nextFree + len + 1 >= stable->size) {
+ assert(stable->size < 1000000);
+ str = (char *) malloc(stable->size*2);
+ memcpy(str, stable->strings, stable->size);
+ free(stable->strings);
+ stable->strings = str;
+ }
+ loc = stable->nextFree;
+ strcpy(&stable->strings[loc], s);
+ stable->nextFree += len + 1;
+ return loc;
+} // AddString
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////// Hash table: ///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#define INIT_HASH_TABLE_SIZE 2047
+#define HASH_TABLE_MAX_COLLISIONS 3
+
+typedef struct HashEntry_Rec {
+ int index; // String table offset of string representation
+ int value; // Atom (symbol) value
+} HashEntry;
+
+typedef struct HashTable_Rec {
+ HashEntry *entry;
+ int size;
+ int entries;
+ int counts[HASH_TABLE_MAX_COLLISIONS + 1];
+} HashTable;
+
+/*
+ * InitHashTable() - Initialize the hash table.
+ *
+ */
+
+static int InitHashTable(HashTable *htable, int fsize)
+{
+ int ii;
+
+ htable->entry = (HashEntry *) malloc(sizeof(HashEntry)*fsize);
+ if (!htable->entry)
+ return 0;
+ htable->size = fsize;
+ for (ii = 0; ii < fsize; ii++) {
+ htable->entry[ii].index = 0;
+ htable->entry[ii].value = 0;
+ }
+ htable->entries = 0;
+ for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++)
+ htable->counts[ii] = 0;
+ return 1;
+} // InitHashTable
+
+/*
+ * FreeHashTable() - Free the hash table.
+ *
+ */
+
+static void FreeHashTable(HashTable *htable)
+{
+ if (htable->entry)
+ free(htable->entry);
+ htable->entry = NULL;
+ htable->size = 0;
+ htable->entries = 0;
+} // FreeHashTable
+
+/*
+ * Empty() - See if a hash table entry is empty.
+ *
+ */
+
+static int Empty(HashTable *htable, int hashloc)
+{
+ assert(hashloc >= 0 && hashloc < htable->size);
+ if (htable->entry[hashloc].index == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+} // Empty
+
+/*
+ * Match() - See if a hash table entry is matches a string.
+ *
+ */
+
+static int Match(HashTable *htable, StringTable *stable, const char *s, int hashloc)
+{
+ int strloc;
+
+ strloc = htable->entry[hashloc].index;
+ if (!strcmp(s, &stable->strings[strloc])) {
+ return 1;
+ } else {
+ return 0;
+ }
+} // Match
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////// Atom table: ///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#define INIT_ATOM_TABLE_SIZE 1024
+
+
+struct AtomTable_Rec {
+ StringTable stable; // String table.
+ HashTable htable; // Hashes string to atom number and token value. Multiple strings can
+ // have the same token value but each unique string is a unique atom.
+ int *amap; // Maps atom value to offset in string table. Atoms all map to unique
+ // strings except for some undefined values in the lower, fixed part
+ // of the atom table that map to "<undefined>". The lowest 256 atoms
+ // correspond to single character ASCII values except for alphanumeric
+ // characters and '_', which can be other tokens. Next come the
+ // language tokens with their atom values equal to the token value.
+ // Then come predefined atoms, followed by user specified identifiers.
+ int *arev; // Reversed atom for symbol table use.
+ int nextFree;
+ int size;
+};
+
+static AtomTable latable = { { 0 } };
+AtomTable *atable = &latable;
+
+static int AddAtomFixed(AtomTable *atable, const char *s, int atom);
+
+/*
+ * GrowAtomTable() - Grow the atom table to at least "size" if it's smaller.
+ *
+ */
+
+static int GrowAtomTable(AtomTable *atable, int size)
+{
+ int *newmap, *newrev;
+
+ if (atable->size < size) {
+ if (atable->amap) {
+ newmap = realloc(atable->amap, sizeof(int)*size);
+ newrev = realloc(atable->arev, sizeof(int)*size);
+ } else {
+ newmap = malloc(sizeof(int)*size);
+ newrev = malloc(sizeof(int)*size);
+ atable->size = 0;
+ }
+ if (!newmap || !newrev) {
+ /* failed to grow -- error */
+ if (newmap)
+ atable->amap = newmap;
+ if (newrev)
+ atable->amap = newrev;
+ return -1;
+ }
+ memset(&newmap[atable->size], 0, (size - atable->size) * sizeof(int));
+ memset(&newrev[atable->size], 0, (size - atable->size) * sizeof(int));
+ atable->amap = newmap;
+ atable->arev = newrev;
+ atable->size = size;
+ }
+ return 0;
+} // GrowAtomTable
+
+/*
+ * lReverse() - Reverse the bottom 20 bits of a 32 bit int.
+ *
+ */
+
+static int lReverse(int fval)
+{
+ unsigned int in = fval;
+ int result = 0, cnt = 0;
+
+ while(in) {
+ result <<= 1;
+ result |= in&1;
+ in >>= 1;
+ cnt++;
+ }
+
+ // Don't use all 31 bits. One million atoms is plenty and sometimes the
+ // upper bits are used for other things.
+
+ if (cnt < 20)
+ result <<= 20 - cnt;
+ return result;
+} // lReverse
+
+/*
+ * AllocateAtom() - Allocate a new atom. Associated with the "undefined" value of -1.
+ *
+ */
+
+static int AllocateAtom(AtomTable *atable)
+{
+ if (atable->nextFree >= atable->size)
+ GrowAtomTable(atable, atable->nextFree*2);
+ atable->amap[atable->nextFree] = -1;
+ atable->arev[atable->nextFree] = lReverse(atable->nextFree);
+ atable->nextFree++;
+ return atable->nextFree - 1;
+} // AllocateAtom
+
+/*
+ * SetAtomValue() - Allocate a new atom associated with "hashindex".
+ *
+ */
+
+static void SetAtomValue(AtomTable *atable, int atomnumber, int hashindex)
+{
+ atable->amap[atomnumber] = atable->htable.entry[hashindex].index;
+ atable->htable.entry[hashindex].value = atomnumber;
+} // SetAtomValue
+
+/*
+ * FindHashLoc() - Find the hash location for this string. Return -1 it hash table is full.
+ *
+ */
+
+static int FindHashLoc(AtomTable *atable, const char *s)
+{
+ int hashloc, hashdelta, count;
+ int FoundEmptySlot = 0;
+ int collision[HASH_TABLE_MAX_COLLISIONS + 1];
+
+ hashloc = HashString(s) % atable->htable.size;
+ if (!Empty(&atable->htable, hashloc)) {
+ if (Match(&atable->htable, &atable->stable, s, hashloc))
+ return hashloc;
+ collision[0] = hashloc;
+ hashdelta = HashString2(s);
+ count = 0;
+ while (count < HASH_TABLE_MAX_COLLISIONS) {
+ hashloc = ((hashloc + hashdelta) & 0x7fffffff) % atable->htable.size;
+ if (!Empty(&atable->htable, hashloc)) {
+ if (Match(&atable->htable, &atable->stable, s, hashloc)) {
+ return hashloc;
+ }
+ } else {
+ FoundEmptySlot = 1;
+ break;
+ }
+ count++;
+ collision[count] = hashloc;
+ }
+
+ if (!FoundEmptySlot) {
+ if (cpp->options.DumpAtomTable) {
+ int ii;
+ char str[200];
+ sprintf(str, "*** Hash failed with more than %d collisions. Must increase hash table size. ***",
+ HASH_TABLE_MAX_COLLISIONS);
+ CPPShInfoLogMsg(str);
+
+ sprintf(str, "*** New string \"%s\", hash=%04x, delta=%04x", s, collision[0], hashdelta);
+ CPPShInfoLogMsg(str);
+ for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++) {
+ sprintf(str, "*** Collides on try %d at hash entry %04x with \"%s\"",
+ ii + 1, collision[ii], GetAtomString(atable, atable->htable.entry[collision[ii]].value));
+ CPPShInfoLogMsg(str);
+ }
+ }
+ return -1;
+ } else {
+ atable->htable.counts[count]++;
+ }
+ }
+ return hashloc;
+} // FindHashLoc
+
+/*
+ * IncreaseHashTableSize()
+ *
+ */
+
+static int IncreaseHashTableSize(AtomTable *atable)
+{
+ int ii, strloc, oldhashloc, value, size;
+ AtomTable oldtable;
+ char *s;
+
+ // Save the old atom table and create a new one:
+
+ oldtable = *atable;
+ size = oldtable.htable.size*2 + 1;
+ if (!InitAtomTable(atable, size))
+ return 0;
+
+ // Add all the existing values to the new atom table preserving their atom values:
+
+ for (ii = atable->nextFree; ii < oldtable.nextFree; ii++) {
+ strloc = oldtable.amap[ii];
+ s = &oldtable.stable.strings[strloc];
+ oldhashloc = FindHashLoc(&oldtable, s);
+ assert(oldhashloc >= 0);
+ value = oldtable.htable.entry[oldhashloc].value;
+ AddAtomFixed(atable, s, value);
+ }
+ FreeAtomTable(&oldtable);
+ return 1;
+} // IncreaseHashTableSize
+
+/*
+ * LookUpAddStringHash() - Lookup a string in the hash table. If it's not there, add it and
+ * initialize the atom value in the hash table to 0. Return the hash table index.
+ */
+
+static int LookUpAddStringHash(AtomTable *atable, const char *s)
+{
+ int hashloc, strloc;
+
+ while(1) {
+ hashloc = FindHashLoc(atable, s);
+ if (hashloc >= 0)
+ break;
+ IncreaseHashTableSize(atable);
+ }
+
+ if (Empty(&atable->htable, hashloc)) {
+ atable->htable.entries++;
+ strloc = AddString(&atable->stable, s);
+ atable->htable.entry[hashloc].index = strloc;
+ atable->htable.entry[hashloc].value = 0;
+ }
+ return hashloc;
+} // LookUpAddStringHash
+
+/*
+ * LookUpAddString() - Lookup a string in the hash table. If it's not there, add it and
+ * initialize the atom value in the hash table to the next atom number.
+ * Return the atom value of string.
+ */
+
+int LookUpAddString(AtomTable *atable, const char *s)
+{
+ int hashindex, atom;
+
+ hashindex = LookUpAddStringHash(atable, s);
+ atom = atable->htable.entry[hashindex].value;
+ if (atom == 0) {
+ atom = AllocateAtom(atable);
+ SetAtomValue(atable, atom, hashindex);
+ }
+ return atom;
+} // LookUpAddString
+
+/*
+ * GetAtomString()
+ *
+ */
+
+const char *GetAtomString(AtomTable *atable, int atom)
+{
+ int soffset;
+
+ if (atom > 0 && atom < atable->nextFree) {
+ soffset = atable->amap[atom];
+ if (soffset > 0 && soffset < atable->stable.nextFree) {
+ return &atable->stable.strings[soffset];
+ } else {
+ return "<internal error: bad soffset>";
+ }
+ } else {
+ if (atom == 0) {
+ return "<null atom>";
+ } else {
+ if (atom == EOF) {
+ return "<EOF>";
+ } else {
+ return "<invalid atom>";
+ }
+ }
+ }
+} // GetAtomString
+
+/*
+ * GetReversedAtom()
+ *
+ */
+
+int GetReversedAtom(AtomTable *atable, int atom)
+{
+ if (atom > 0 && atom < atable->nextFree) {
+ return atable->arev[atom];
+ } else {
+ return 0;
+ }
+} // GetReversedAtom
+
+/*
+ * AddAtom() - Add a string to the atom, hash and string tables if it isn't already there.
+ * Return it's atom index.
+ */
+
+int AddAtom(AtomTable *atable, const char *s)
+{
+ int atom;
+
+ atom = LookUpAddString(atable, s);
+ return atom;
+} // AddAtom
+
+/*
+ * AddAtomFixed() - Add an atom to the hash and string tables if it isn't already there.
+ * Assign it the atom value of "atom".
+ */
+
+static int AddAtomFixed(AtomTable *atable, const char *s, int atom)
+{
+ int hashindex, lsize;
+
+ hashindex = LookUpAddStringHash(atable, s);
+ if (atable->nextFree >= atable->size || atom >= atable->size) {
+ lsize = atable->size*2;
+ if (lsize <= atom)
+ lsize = atom + 1;
+ GrowAtomTable(atable, lsize);
+ }
+ atable->amap[atom] = atable->htable.entry[hashindex].index;
+ atable->htable.entry[hashindex].value = atom;
+ //if (atom >= atable->nextFree)
+ // atable->nextFree = atom + 1;
+ while (atom >= atable->nextFree) {
+ atable->arev[atable->nextFree] = lReverse(atable->nextFree);
+ atable->nextFree++;
+ }
+ return atom;
+} // AddAtomFixed
+
+/*
+ * InitAtomTable() - Initialize the atom table.
+ *
+ */
+
+int InitAtomTable(AtomTable *atable, int htsize)
+{
+ 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++) {
+ sprintf(str, "%d: \"%s\"", ii, &atable->stable.strings[atable->amap[ii]]);
+ CPPDebugLogMsg(str);
+ }
+ sprintf(str, "Hash table: size=%d, entries=%d, collisions=",
+ atable->htable.size, atable->htable.entries);
+ CPPDebugLogMsg(str);
+ for (ii = 0; ii < HASH_TABLE_MAX_COLLISIONS; ii++) {
+ sprintf(str, " %d", atable->htable.counts[ii]);
+ CPPDebugLogMsg(str);
+ }
+
+} // PrintAtomTable
+
+
+/*
+ * GetStringOfAtom()
+ *
+ */
+
+char* GetStringOfAtom(AtomTable *atable, int atom)
+{
+ char* chr_str;
+ chr_str=&atable->stable.strings[atable->amap[atom]];
+ return chr_str;
+} // GetStringOfAtom
+
+/*
+ * FreeAtomTable() - Free the atom table and associated memory
+ *
+ */
+
+void FreeAtomTable(AtomTable *atable)
+{
+ FreeStringTable(&atable->stable);
+ FreeHashTable(&atable->htable);
+ if (atable->amap)
+ free(atable->amap);
+ if (atable->arev)
+ free(atable->arev);
+ atable->amap = NULL;
+ atable->arev = NULL;
+ atable->nextFree = 0;
+ atable->size = 0;
+} // FreeAtomTable
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////// End of atom.c ///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/atom.h b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/atom.h
new file mode 100644
index 0000000..1d84c32
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/atom.h
@@ -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/Source/ThirdParty/ANGLE/src/compiler/preprocessor/compile.h b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/compile.h
new file mode 100644
index 0000000..5bfa902
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/compile.h
@@ -0,0 +1,99 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// compile.h
+//
+
+#if !defined(__COMPILE_H)
+#define __COMPILE_H 1
+
+int InitCPPStruct(void);
+
+typedef struct Options_Rec{
+ const char *profileString;
+ int ErrorMode;
+ int Quiet;
+
+ // Debug The Compiler options:
+ int DumpAtomTable;
+} Options;
+
+struct CPPStruct_Rec {
+ // Public members
+ SourceLoc *pLastSourceLoc; // Set at the start of each statement by the tree walkers
+ Options options; // Compile options and parameters
+
+ // Private members
+ SourceLoc lastSourceLoc;
+
+ // Scanner data:
+
+ SourceLoc *tokenLoc; // Source location of most recent token seen by the scanner
+ int mostRecentToken; // Most recent token seen by the scanner
+ InputSrc *currentInput;
+ int previous_token;
+ int 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[64]; //Keep a track of #if depth..Max allowed is 64.
+ int elsetracker; //#if-#else and #endif constructs...Counter.
+ const char *ErrMsg;
+ int CompileError; //Indicate compile error when #error, #else,#elif mismatch.
+
+ //
+ // Globals used to communicate between PaParseStrings() and yy_input()and
+ // also across the files.(gen_glslang.cpp and scanner.c)
+ //
+ int PaWhichStr; // which string we're parsing
+ int* PaStrLen; // array of lengths of the PaArgv strings
+ int PaArgc; // count of strings in the array
+ char** PaArgv; // our array of strings to parse
+ unsigned int tokensBeforeEOF : 1;
+};
+
+#endif // !defined(__COMPILE_H)
diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.c b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.c
new file mode 100644
index 0000000..f15c56d
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.c
@@ -0,0 +1,1024 @@
+/****************************************************************************\
+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 "compiler/preprocessor/slglobals.h"
+
+static int CPPif(yystypepp * yylvalpp);
+
+/* Don't use memory.c's replacements, as we clean up properly here */
+#undef malloc
+#undef free
+
+static int bindAtom = 0;
+static int constAtom = 0;
+static int defaultAtom = 0;
+static int defineAtom = 0;
+static int definedAtom = 0;
+static int elseAtom = 0;
+static int elifAtom = 0;
+static int endifAtom = 0;
+static int ifAtom = 0;
+static int ifdefAtom = 0;
+static int ifndefAtom = 0;
+static int includeAtom = 0;
+static int lineAtom = 0;
+static int pragmaAtom = 0;
+static int texunitAtom = 0;
+static int undefAtom = 0;
+static int errorAtom = 0;
+static int __LINE__Atom = 0;
+static int __FILE__Atom = 0;
+static int __VERSION__Atom = 0;
+static int versionAtom = 0;
+static int extensionAtom = 0;
+
+static Scope *macros = 0;
+#define MAX_MACRO_ARGS 64
+#define MAX_IF_NESTING 64
+
+static SourceLoc ifloc; /* outermost #if */
+
+int InitCPP(void)
+{
+ char buffer[64], *t;
+ const char *f;
+
+ // Add various atoms needed by the CPP line scanner:
+ bindAtom = LookUpAddString(atable, "bind");
+ constAtom = LookUpAddString(atable, "const");
+ defaultAtom = LookUpAddString(atable, "default");
+ defineAtom = LookUpAddString(atable, "define");
+ definedAtom = LookUpAddString(atable, "defined");
+ elifAtom = LookUpAddString(atable, "elif");
+ elseAtom = LookUpAddString(atable, "else");
+ endifAtom = LookUpAddString(atable, "endif");
+ ifAtom = LookUpAddString(atable, "if");
+ ifdefAtom = LookUpAddString(atable, "ifdef");
+ ifndefAtom = LookUpAddString(atable, "ifndef");
+ includeAtom = LookUpAddString(atable, "include");
+ lineAtom = LookUpAddString(atable, "line");
+ pragmaAtom = LookUpAddString(atable, "pragma");
+ texunitAtom = LookUpAddString(atable, "texunit");
+ undefAtom = LookUpAddString(atable, "undef");
+ errorAtom = LookUpAddString(atable, "error");
+ __LINE__Atom = LookUpAddString(atable, "__LINE__");
+ __FILE__Atom = LookUpAddString(atable, "__FILE__");
+ __VERSION__Atom = LookUpAddString(atable, "__VERSION__");
+ versionAtom = LookUpAddString(atable, "version");
+ extensionAtom = LookUpAddString(atable, "extension");
+ macros = NewScopeInPool(mem_CreatePool(0, 0));
+ strcpy(buffer, "PROFILE_");
+ t = buffer + strlen(buffer);
+ f = cpp->options.profileString;
+ while ((isalnum(*f) || *f == '_') && t < buffer + sizeof(buffer) - 1)
+ *t++ = toupper(*f++);
+ *t = 0;
+
+ 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;
+ }
+ RecordToken(mac.body, token, yylvalpp);
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ };
+
+ symb = LookUpSymbol(macros, name);
+ if (symb) {
+ if (!symb->details.mac.undef) {
+ // already defined -- need to make sure they are identical
+ if (symb->details.mac.argc != mac.argc) goto error;
+ for (argc=0; argc < mac.argc; argc++)
+ if (symb->details.mac.args[argc] != mac.args[argc])
+ goto error;
+ RewindTokenStream(symb->details.mac.body);
+ RewindTokenStream(mac.body);
+ do {
+ int old_lval, old_token;
+ old_token = ReadToken(symb->details.mac.body, yylvalpp);
+ old_lval = yylvalpp->sc_int;
+ token = ReadToken(mac.body, yylvalpp);
+ if (token != old_token || yylvalpp->sc_int != old_lval) {
+ error:
+ StoreStr("Macro Redefined");
+ StoreStr(GetStringOfAtom(atable,name));
+ message=GetStrfromTStr();
+ DecLineNumber();
+ CPPShInfoLogMsg(message);
+ IncLineNumber();
+ ResetTString();
+ break; }
+ } while (token > 0);
+ }
+ //FreeMacro(&symb->details.mac);
+ } else {
+ dummyLoc.file = 0;
+ dummyLoc.line = 0;
+ symb = AddSymbol(&dummyLoc, macros, name, MACRO_S);
+ }
+ symb->details.mac = mac;
+ return '\n';
+} // CPPdefine
+
+static int CPPundef(yystypepp * yylvalpp)
+{
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ Symbol *symb;
+ if(token == '\n'){
+ CPPErrorToInfoLog("#undef");
+ return token;
+ }
+ if (token != CPP_IDENTIFIER)
+ goto error;
+ symb = LookUpSymbol(macros, yylvalpp->sc_ident);
+ if (symb) {
+ symb->details.mac.undef = 1;
+ }
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token != '\n') {
+ error:
+ CPPErrorToInfoLog("#undef");
+ }
+ return token;
+} // CPPundef
+
+/* CPPelse -- skip forward to appropriate spot. This is actually used
+** to skip to and #endif after seeing an #else, AND to skip to a #else,
+** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false
+*/
+
+static int CPPelse(int matchelse, yystypepp * yylvalpp)
+{
+ int atom,depth=0;
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+
+ while (token > 0) {
+ if (token != '#') {
+ while (token != '\n')
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ continue;
+ }
+ if ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) != CPP_IDENTIFIER)
+ continue;
+ atom = yylvalpp->sc_ident;
+ if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom){
+ depth++; cpp->ifdepth++; cpp->elsetracker++;
+ cpp->elsedepth[cpp->elsetracker] = 0;
+ }
+ else if (atom == endifAtom) {
+ if(--depth<0){
+ --cpp->elsetracker;
+ if (cpp->ifdepth)
+ --cpp->ifdepth;
+ break;
+ }
+ --cpp->elsetracker;
+ --cpp->ifdepth;
+ }
+ else if (((int)(matchelse) != 0)&& depth==0) {
+ if (atom == elseAtom ) {
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token != '\n') {
+ CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
+ while (token != '\n')
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+ break;
+ }
+ else if (atom == elifAtom) {
+ /* we decrement cpp->ifdepth here, because CPPif will increment
+ * it and we really want to leave it alone */
+ if (cpp->ifdepth){
+ --cpp->ifdepth;
+ --cpp->elsetracker;
+ }
+ return CPPif(yylvalpp);
+ }
+ }
+ else if((atom==elseAtom) && (!ChkCorrectElseNesting())){
+ CPPErrorToInfoLog("#else after a #else");
+ cpp->CompileError=1;
+ }
+ };
+ return token;
+}
+
+enum eval_prec {
+ MIN_PREC,
+ COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY,
+ MAX_PREC
+};
+
+static int op_logor(int a, int b) { return a || b; }
+static int op_logand(int a, int b) { return a && b; }
+static int op_or(int a, int b) { return a | b; }
+static int op_xor(int a, int b) { return a ^ b; }
+static int op_and(int a, int b) { return a & b; }
+static int op_eq(int a, int b) { return a == b; }
+static int op_ne(int a, int b) { return a != b; }
+static int op_ge(int a, int b) { return a >= b; }
+static int op_le(int a, int b) { return a <= b; }
+static int op_gt(int a, int b) { return a > b; }
+static int op_lt(int a, int b) { return a < b; }
+static int op_shl(int a, int b) { return a << b; }
+static int op_shr(int a, int b) { return a >> b; }
+static int op_add(int a, int b) { return a + b; }
+static int op_sub(int a, int b) { return a - b; }
+static int op_mul(int a, int b) { return a * b; }
+static int op_div(int a, int b) { return a / b; }
+static int op_mod(int a, int b) { return a % b; }
+static int op_pos(int a) { return a; }
+static int op_neg(int a) { return -a; }
+static int op_cmpl(int a) { return ~a; }
+static int op_not(int a) { return !a; }
+
+struct {
+ int token, prec, (*op)(int, int);
+} binop[] = {
+ { CPP_OR_OP, LOGOR, op_logor },
+ { CPP_AND_OP, LOGAND, op_logand },
+ { '|', OR, op_or },
+ { '^', XOR, op_xor },
+ { '&', AND, op_and },
+ { CPP_EQ_OP, EQUAL, op_eq },
+ { CPP_NE_OP, EQUAL, op_ne },
+ { '>', RELATION, op_gt },
+ { CPP_GE_OP, RELATION, op_ge },
+ { '<', RELATION, op_lt },
+ { CPP_LE_OP, RELATION, op_le },
+ { CPP_LEFT_OP, SHIFT, op_shl },
+ { CPP_RIGHT_OP, SHIFT, op_shr },
+ { '+', ADD, op_add },
+ { '-', ADD, op_sub },
+ { '*', MUL, op_mul },
+ { '/', MUL, op_div },
+ { '%', MUL, op_mod },
+};
+
+struct {
+ int token, (*op)(int);
+} unop[] = {
+ { '+', op_pos },
+ { '-', op_neg },
+ { '~', op_cmpl },
+ { '!', op_not },
+};
+
+#define ALEN(A) (sizeof(A)/sizeof(A[0]))
+
+static int eval(int token, int prec, int *res, int *err, yystypepp * yylvalpp)
+{
+ int i, val;
+ Symbol *s;
+ if (token == CPP_IDENTIFIER) {
+ if (yylvalpp->sc_ident == definedAtom) {
+ int needclose = 0;
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token == '(') {
+ needclose = 1;
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+ if (token != CPP_IDENTIFIER)
+ goto error;
+ *res = (s = LookUpSymbol(macros, yylvalpp->sc_ident))
+ ? !s->details.mac.undef : 0;
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (needclose) {
+ if (token != ')')
+ goto error;
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+ } else if (MacroExpand(yylvalpp->sc_ident, yylvalpp)) {
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ return eval(token, prec, res, err, yylvalpp);
+ } else {
+ goto error;
+ }
+ } else if (token == CPP_INTCONSTANT) {
+ *res = yylvalpp->sc_int;
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ } else if (token == '(') {
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ token = eval(token, MIN_PREC, res, err, yylvalpp);
+ if (!*err) {
+ if (token != ')')
+ goto error;
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+ } else {
+ for (i = ALEN(unop) - 1; i >= 0; i--) {
+ if (unop[i].token == token)
+ break;
+ }
+ if (i >= 0) {
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ token = eval(token, UNARY, res, err, yylvalpp);
+ *res = unop[i].op(*res);
+ } else {
+ goto error;
+ }
+ }
+ while (!*err) {
+ if (token == ')' || token == '\n') break;
+ for (i = ALEN(binop) - 1; i >= 0; i--) {
+ if (binop[i].token == token)
+ break;
+ }
+ if (i < 0 || binop[i].prec <= prec)
+ break;
+ val = *res;
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ token = eval(token, binop[i].prec, res, err, yylvalpp);
+ *res = binop[i].op(val, *res);
+ }
+ return token;
+error:
+ CPPErrorToInfoLog("incorrect preprocessor directive");
+ *err = 1;
+ *res = 0;
+ return token;
+} // eval
+
+static int CPPif(yystypepp * yylvalpp) {
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ int res = 0, err = 0;
+ cpp->elsetracker++;
+ cpp->elsedepth[cpp->elsetracker] = 0;
+ if (!cpp->ifdepth++)
+ ifloc = *cpp->tokenLoc;
+ if(cpp->ifdepth >MAX_IF_NESTING){
+ CPPErrorToInfoLog("max #if nesting depth exceeded");
+ return 0;
+ }
+ token = eval(token, MIN_PREC, &res, &err, yylvalpp);
+ if (token != '\n') {
+ CPPWarningToInfoLog("unexpected tokens following the preprocessor directive - expected a newline");
+ while (token != '\n')
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+ if (!res && !err) {
+ token = CPPelse(1, yylvalpp);
+ }
+
+ return token;
+} // CPPif
+
+static int CPPifdef(int defined, yystypepp * yylvalpp)
+{
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ int name = yylvalpp->sc_ident;
+ if(++cpp->ifdepth >MAX_IF_NESTING){
+ CPPErrorToInfoLog("max #if nesting depth exceeded");
+ return 0;
+ }
+ cpp->elsetracker++;
+ 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 (((s && !s->details.mac.undef) ? 1 : 0) != defined)
+ token = CPPelse(1, yylvalpp);
+ }
+ return token;
+} // CPPifdef
+
+static int CPPline(yystypepp * yylvalpp)
+{
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if(token=='\n'){
+ DecLineNumber();
+ CPPErrorToInfoLog("#line");
+ IncLineNumber();
+ return token;
+ }
+ else if (token == CPP_INTCONSTANT) {
+ yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+ SetLineNumber(yylvalpp->sc_int);
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+
+ if (token == CPP_INTCONSTANT) {
+ yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+ SetStringNumber(yylvalpp->sc_int);
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if(token!='\n')
+ CPPErrorToInfoLog("#line");
+ }
+ else if (token == '\n'){
+ return token;
+ }
+ else{
+ CPPErrorToInfoLog("#line");
+ }
+ }
+ else{
+ CPPErrorToInfoLog("#line");
+ }
+ return token;
+}
+
+static int CPPerror(yystypepp * yylvalpp) {
+
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ const char *message;
+
+ while (token != '\n') {
+ if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){
+ StoreStr(yylvalpp->symbol_name);
+ }else if(token == CPP_IDENTIFIER || token == CPP_STRCONSTANT){
+ StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
+ }else {
+ StoreStr(GetStringOfAtom(atable,token));
+ }
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+ DecLineNumber();
+ //store this msg into the shader's information log..set the Compile Error flag!!!!
+ message=GetStrfromTStr();
+ CPPShInfoLogMsg(message);
+ ResetTString();
+ cpp->CompileError=1;
+ IncLineNumber();
+ return '\n';
+}//CPPerror
+
+static int CPPpragma(yystypepp * yylvalpp)
+{
+ char SrcStrName[2];
+ char** allTokens;
+ int tokenCount = 0;
+ int maxTokenCount = 10;
+ const char* SrcStr;
+ int i;
+
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+
+ if (token=='\n') {
+ DecLineNumber();
+ CPPErrorToInfoLog("#pragma");
+ IncLineNumber();
+ return token;
+ }
+
+ allTokens = (char**)malloc(sizeof(char*) * maxTokenCount);
+
+ while (token != '\n') {
+ if (tokenCount >= maxTokenCount) {
+ maxTokenCount *= 2;
+ allTokens = (char**)realloc((char**)allTokens, sizeof(char*) * maxTokenCount);
+ }
+ switch (token) {
+ case CPP_IDENTIFIER:
+ SrcStr = GetAtomString(atable, yylvalpp->sc_ident);
+ allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
+ strcpy(allTokens[tokenCount++], SrcStr);
+ break;
+ case CPP_INTCONSTANT:
+ SrcStr = yylvalpp->symbol_name;
+ allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
+ strcpy(allTokens[tokenCount++], SrcStr);
+ break;
+ case CPP_FLOATCONSTANT:
+ SrcStr = yylvalpp->symbol_name;
+ allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
+ strcpy(allTokens[tokenCount++], SrcStr);
+ break;
+ case -1:
+ // EOF
+ CPPShInfoLogMsg("#pragma directive must end with a newline");
+ return token;
+ default:
+ SrcStrName[0] = token;
+ SrcStrName[1] = '\0';
+ allTokens[tokenCount] = (char*)malloc(2);
+ strcpy(allTokens[tokenCount++], SrcStrName);
+ }
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+
+ cpp->currentInput->ungetch(cpp->currentInput, token, yylvalpp);
+ HandlePragma((const char**)allTokens, tokenCount);
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+
+ for (i = 0; i < tokenCount; ++i) {
+ free (allTokens[i]);
+ }
+ free (allTokens);
+
+ return token;
+} // CPPpragma
+
+#define 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[80];
+
+ if(token=='\n'){
+ DecLineNumber();
+ CPPShInfoLogMsg("extension name not specified");
+ IncLineNumber();
+ return token;
+ }
+
+ if (token != CPP_IDENTIFIER)
+ CPPErrorToInfoLog("#extension");
+
+ strcpy(extensionName, GetAtomString(atable, yylvalpp->sc_ident));
+
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token != ':') {
+ CPPShInfoLogMsg("':' missing after extension name");
+ return token;
+ }
+
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token != CPP_IDENTIFIER) {
+ CPPShInfoLogMsg("behavior for extension not specified");
+ return token;
+ }
+
+ updateExtensionBehavior(extensionName, GetAtomString(atable, yylvalpp->sc_ident));
+
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token == '\n'){
+ return token;
+ }
+ else{
+ CPPErrorToInfoLog("#extension");
+ }
+ return token;
+} // CPPextension
+
+int readCPPline(yystypepp * yylvalpp)
+{
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ const char *message;
+ int isVersion = 0;
+
+ if (token == CPP_IDENTIFIER) {
+ if (yylvalpp->sc_ident == defineAtom) {
+ token = CPPdefine(yylvalpp);
+ } else if (yylvalpp->sc_ident == elseAtom) {
+ if(ChkCorrectElseNesting()){
+ if (!cpp->ifdepth ){
+ CPPErrorToInfoLog("#else mismatch");
+ cpp->CompileError=1;
+ }
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token != '\n') {
+ CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
+ while (token != '\n')
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+ token = CPPelse(0, yylvalpp);
+ }else{
+ CPPErrorToInfoLog("#else after a #else");
+ cpp->ifdepth=0;
+ cpp->pastFirstStatement = 1;
+ return 0;
+ }
+ } else if (yylvalpp->sc_ident == elifAtom) {
+ if (!cpp->ifdepth){
+ CPPErrorToInfoLog("#elif mismatch");
+ cpp->CompileError=1;
+ }
+ // this token is really a dont care, but we still need to eat the tokens
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ while (token != '\n')
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ token = CPPelse(0, yylvalpp);
+ } else if (yylvalpp->sc_ident == endifAtom) {
+ --cpp->elsetracker;
+ if (!cpp->ifdepth){
+ CPPErrorToInfoLog("#endif mismatch");
+ cpp->CompileError=1;
+ }
+ else
+ --cpp->ifdepth;
+ } else if (yylvalpp->sc_ident == ifAtom) {
+ token = CPPif(yylvalpp);
+ } else if (yylvalpp->sc_ident == ifdefAtom) {
+ token = CPPifdef(1, yylvalpp);
+ } else if (yylvalpp->sc_ident == ifndefAtom) {
+ token = CPPifdef(0, yylvalpp);
+ } else if (yylvalpp->sc_ident == lineAtom) {
+ token = CPPline(yylvalpp);
+ } else if (yylvalpp->sc_ident == pragmaAtom) {
+ token = CPPpragma(yylvalpp);
+ } else if (yylvalpp->sc_ident == undefAtom) {
+ token = CPPundef(yylvalpp);
+ } else if (yylvalpp->sc_ident == errorAtom) {
+ token = CPPerror(yylvalpp);
+ } else if (yylvalpp->sc_ident == versionAtom) {
+ token = CPPversion(yylvalpp);
+ isVersion = 1;
+ } else if (yylvalpp->sc_ident == extensionAtom) {
+ token = CPPextension(yylvalpp);
+ } else {
+ StoreStr("Invalid Directive");
+ StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
+ message=GetStrfromTStr();
+ CPPShInfoLogMsg(message);
+ ResetTString();
+ }
+ }
+ while (token != '\n' && token != 0 && token != EOF) {
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+
+ cpp->pastFirstStatement = 1;
+
+ return token;
+} // readCPPline
+
+void FreeMacro(MacroSymbol *s) {
+ DeleteTokenStream(s->body);
+}
+
+void PredefineIntMacro(const char *name, int value) {
+ SourceLoc location = {0};
+ Symbol *symbol = NULL;
+ MacroSymbol macro = {0};
+ yystypepp val = {0};
+ int atom = 0;
+
+ macro.body = NewTokenStream(name, macros->pool);
+ val.sc_int = value;
+ sprintf(val.symbol_name, "%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();
+ sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int);
+ UngetToken(CPP_INTCONSTANT, yylvalpp);
+ return 1;
+ }
+ if (atom == __FILE__Atom) {
+ yylvalpp->sc_int = GetStringNumber();
+ sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int);
+ UngetToken(CPP_INTCONSTANT, yylvalpp);
+ return 1;
+ }
+ if (atom == __VERSION__Atom) {
+ strcpy(yylvalpp->symbol_name,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)
+{
+ if(cpp->elsedepth[cpp->elsetracker]==0){
+ cpp->elsedepth[cpp->elsetracker]=1;
+ return 1;
+ }
+ return 0;
+}
+
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.h b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.h
new file mode 100644
index 0000000..db4c184
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.h
@@ -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(char*); // Stick all cpp errors into Sh.Info.log .
+void StoreStr(char*); // Store the TString in Parse Context.
+void SetLineNumber(int); // Set line number.
+void SetStringNumber(int); // Set string number.
+int GetLineNumber(void); // Get the current String Number.
+int GetStringNumber(void); // Get the current String Number.
+const char* GetStrfromTStr(void); // Convert TString to String.
+void updateExtensionBehavior(const char* extName, const char* behavior);
+int FreeCPP(void);
+
+#endif // !(defined(__CPP_H)
diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cppstruct.c b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cppstruct.c
new file mode 100644
index 0000000..8e142bc
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cppstruct.c
@@ -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<64; cpp->elsetracker++)
+ cpp->elsedepth[cpp->elsetracker]=0;
+ cpp->elsetracker=0;
+ cpp->tokensBeforeEOF = 0;
+ return 1;
+}
+
+//Intializing the Preprocessor.
+
+int InitPreprocessor(void)
+{
+ # define CPP_STUFF true
+ # ifdef CPP_STUFF
+ FreeCPPStruct();
+ InitCPPStruct();
+ cpp->options.Quiet = 1;
+ cpp->options.profileString = "generic";
+ if (!InitAtomTable(atable, 0))
+ return 1;
+ if (!InitScanner(cpp))
+ return 1;
+ # endif
+ return 0;
+}
+
+//FreeCPPStruct() - Free the CPP structure.
+
+int FreeCPPStruct(void)
+{
+ if (refCount)
+ {
+ free(cpp);
+ refCount--;
+ }
+
+ return 1;
+}
+
+//Finalizing the Preprocessor.
+
+int FinalizePreprocessor(void)
+{
+ # define CPP_STUFF true
+ # ifdef CPP_STUFF
+ FreeAtomTable(atable);
+ FreeCPPStruct();
+ FreeScanner();
+ # endif
+ return 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////// End of cppstruct.c //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/memory.c b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/memory.c
new file mode 100644
index 0000000..e6fea7a
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/memory.c
@@ -0,0 +1,154 @@
+/****************************************************************************\
+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"
+
+// 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/Source/ThirdParty/ANGLE/src/compiler/preprocessor/memory.h b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/memory.h
new file mode 100644
index 0000000..b3ae2f9
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/memory.h
@@ -0,0 +1,56 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+#ifndef __MEMORY_H
+#define __MEMORY_H
+
+typedef struct MemoryPool_rec MemoryPool;
+
+extern MemoryPool *mem_CreatePool(size_t chunksize, unsigned 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/Source/ThirdParty/ANGLE/src/compiler/preprocessor/parser.h b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/parser.h
new file mode 100644
index 0000000..f67342b
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/parser.h
@@ -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/Source/ThirdParty/ANGLE/src/compiler/preprocessor/preprocess.h b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/preprocess.h
new file mode 100644
index 0000000..0602c91
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/preprocess.h
@@ -0,0 +1,51 @@
+/****************************************************************************\
+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);
+int ScanFromString(char *s);
+char* GetStringOfAtom(AtomTable *atable, int atom);
diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/scanner.c b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/scanner.c
new file mode 100644
index 0000000..c77d271
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/scanner.c
@@ -0,0 +1,759 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// scanner.c
+//
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+ #include <ieeefp.h>
+ #else
+ #define isinff(x) (((*(int *)&(x) & 0x7f800000L)==0x7f800000L) && \
+ ((*(int *)&(x) & 0x007fffffL)==0000000000L))
+#endif
+
+#include "compiler/preprocessor/slglobals.h"
+
+
+typedef struct StringInputSrc {
+ InputSrc base;
+ char *p;
+} StringInputSrc;
+
+static int eof_scan(InputSrc *is, yystypepp * yylvalpp)
+{
+ return EOF;
+} // eof_scan
+
+static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) {}
+
+static InputSrc eof_inputsrc = { 0, &eof_scan, &eof_scan, &noop };
+
+static int byte_scan(InputSrc *, yystypepp * yylvalpp);
+
+#define EOL_SY '\n'
+
+#if defined(_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());
+}
+
+/*
+ * str_getch()
+ * takes care of reading from multiple strings.
+ * returns the next-char from the input stream.
+ * returns EOF when the complete shader is parsed.
+ */
+static int str_getch(StringInputSrc *in)
+{
+ for(;;){
+ if (*in->p){
+ if (*in->p == '\n') {
+ in->base.line++;
+ IncLineNumber();
+ }
+ return *in->p++;
+ }
+ if(++(cpp->PaWhichStr) < cpp->PaArgc){
+ free(in);
+ SetStringNumber(cpp->PaWhichStr);
+ SetLineNumber(1);
+ ScanFromString(cpp->PaArgv[cpp->PaWhichStr]);
+ in=(StringInputSrc*)cpp->currentInput;
+ continue;
+ }
+ else{
+ cpp->currentInput = in->base.prev;
+ cpp->PaWhichStr=0;
+ free(in);
+ return EOF;
+ }
+ }
+} // str_getch
+
+static void str_ungetch(StringInputSrc *in, int ch, yystypepp *type) {
+ if (in->p[-1] == ch)in->p--;
+ else {
+ *(in->p)='\0'; //this would take care of shifting to the previous string.
+ cpp->PaWhichStr--;
+ }
+ if (ch == '\n') {
+ in->base.line--;
+ DecLineNumber();
+ }
+} // str_ungetch
+
+int ScanFromString(char *s)
+{
+
+ StringInputSrc *in = malloc(sizeof(StringInputSrc));
+ memset(in, 0, sizeof(StringInputSrc));
+ in->p = s;
+ in->base.line = 1;
+ in->base.scan = byte_scan;
+ in->base.getch = (int (*)(InputSrc *, yystypepp *))str_getch;
+ in->base.ungetch = (void (*)(InputSrc *, int, yystypepp *))str_ungetch;
+ in->base.prev = cpp->currentInput;
+ cpp->currentInput = &in->base;
+
+ return 1;
+} // ScanFromString;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////// Floating point constants: /////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ * lBuildFloatValue() - Quick and dirty conversion to floating point. Since all
+ * we need is single precision this should be quite precise.
+ */
+
+static float lBuildFloatValue(const char *str, int len, int exp)
+{
+ double val, expval, ten;
+ int ii, llen, absexp;
+ float rv;
+
+ val = 0.0;
+ llen = len;
+ for (ii = 0; ii < len; ii++)
+ val = val*10.0 + (str[ii] - '0');
+ if (exp != 0) {
+ absexp = exp > 0 ? exp : -exp;
+ expval = 1.0f;
+ ten = 10.0;
+ while (absexp) {
+ if (absexp & 1)
+ expval *= ten;
+ ten *= ten;
+ absexp >>= 1;
+ }
+ if (exp >= 0) {
+ val *= expval;
+ } else {
+ val /= expval;
+ }
+ }
+ rv = (float)val;
+ if (isinff(rv)) {
+ CPPErrorToInfoLog(" ERROR___FP_CONST_OVERFLOW");
+ }
+ return rv;
+} // lBuildFloatValue
+
+
+/*
+ * lFloatConst() - Scan a floating point constant. Assumes that the scanner
+ * has seen at least one digit, followed by either a decimal '.' or the
+ * letter 'e'.
+ */
+
+static int lFloatConst(char *str, int len, int ch, yystypepp * yylvalpp)
+{
+ int HasDecimal, declen, exp, ExpSign;
+ int str_len;
+ float lval;
+
+ HasDecimal = 0;
+ declen = 0;
+ exp = 0;
+
+ str_len=len;
+ if (ch == '.') {
+ str[len++]=ch;
+ HasDecimal = 1;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ while (ch >= '0' && ch <= '9') {
+ if (len < MAX_SYMBOL_NAME_LEN) {
+ declen++;
+ if (len > 0 || ch != '0') {
+ str[len] = ch;
+ len++;str_len++;
+ }
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ } else {
+ CPPErrorToInfoLog("ERROR___FP_CONST_TOO_LONG");
+ len = 1,str_len=1;
+ }
+ }
+ }
+
+ // Exponent:
+
+ if (ch == 'e' || ch == 'E') {
+ ExpSign = 1;
+ str[len++]=ch;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '+') {
+ str[len++]=ch;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ } else if (ch == '-') {
+ ExpSign = -1;
+ str[len++]=ch;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ }
+ if (ch >= '0' && ch <= '9') {
+ while (ch >= '0' && ch <= '9') {
+ exp = exp*10 + ch - '0';
+ str[len++]=ch;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ }
+ } else {
+ CPPErrorToInfoLog("ERROR___ERROR_IN_EXPONENT");
+ }
+ exp *= ExpSign;
+ }
+
+ if (len == 0) {
+ lval = 0.0f;
+ strcpy(str,"0.0");
+ } else {
+ str[len]='\0';
+ lval = lBuildFloatValue(str, str_len, exp - declen);
+ }
+ // Suffix:
+
+ yylvalpp->sc_fval = lval;
+ strcpy(yylvalpp->symbol_name,str);
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return CPP_FLOATCONSTANT;
+} // lFloatConst
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////// Normal Scanner //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
+{
+ char symbol_name[MAX_SYMBOL_NAME_LEN + 1];
+ char string_val[MAX_STRING_LEN + 1];
+ int AlreadyComplained;
+ int len, ch, ii, ival = 0;
+
+ for (;;) {
+ yylvalpp->sc_int = 0;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+
+ while (ch == ' ' || ch == '\t' || ch == '\r') {
+ yylvalpp->sc_int = 1;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ }
+
+ cpp->ltokenLoc.file = cpp->currentInput->name;
+ cpp->ltokenLoc.line = cpp->currentInput->line;
+ len = 0;
+ switch (ch) {
+ default:
+ return ch; // Single character token
+ case EOF:
+ return -1;
+ case 'A': case 'B': case 'C': case 'D': case 'E':
+ case 'F': case 'G': case 'H': case 'I': case 'J':
+ case 'K': case 'L': case 'M': case 'N': case 'O':
+ case 'P': case 'Q': case 'R': case 'S': case 'T':
+ case 'U': case 'V': case 'W': case 'X': case 'Y':
+ case 'Z': case '_':
+ case 'a': case 'b': case 'c': case 'd': case 'e':
+ case 'f': case 'g': case 'h': case 'i': case 'j':
+ case 'k': case 'l': case 'm': case 'n': case 'o':
+ case 'p': case 'q': case 'r': case 's': case 't':
+ case 'u': case 'v': case 'w': case 'x': case 'y':
+ case 'z':
+ do {
+ if (len < MAX_SYMBOL_NAME_LEN) {
+ symbol_name[len] = ch;
+ len++;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ } else {
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ }
+ } while ((ch >= 'a' && ch <= 'z') ||
+ (ch >= 'A' && ch <= 'Z') ||
+ (ch >= '0' && ch <= '9') ||
+ ch == '_');
+ if (len >= MAX_SYMBOL_NAME_LEN)
+ len = MAX_SYMBOL_NAME_LEN - 1;
+ symbol_name[len] = '\0';
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ yylvalpp->sc_ident = LookUpAddString(atable, symbol_name);
+ return CPP_IDENTIFIER;
+ break;
+ case '0':
+ yylvalpp->symbol_name[len++] = ch;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == 'x' || ch == 'X') {
+ yylvalpp->symbol_name[len++] = ch;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if ((ch >= '0' && ch <= '9') ||
+ (ch >= 'A' && ch <= 'F') ||
+ (ch >= 'a' && ch <= 'f'))
+ {
+ AlreadyComplained = 0;
+ ival = 0;
+ do {
+ yylvalpp->symbol_name[len++] = ch;
+ if (ival <= 0x0fffffff) {
+ if (ch >= '0' && ch <= '9') {
+ ii = ch - '0';
+ } else if (ch >= 'A' && ch <= 'F') {
+ ii = ch - 'A' + 10;
+ } else {
+ ii = ch - 'a' + 10;
+ }
+ ival = (ival << 4) | ii;
+ } else {
+ if (!AlreadyComplained)
+ CPPErrorToInfoLog("ERROR___HEX_CONST_OVERFLOW");
+ AlreadyComplained = 1;
+ }
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ } while ((ch >= '0' && ch <= '9') ||
+ (ch >= 'A' && ch <= 'F') ||
+ (ch >= 'a' && ch <= 'f'));
+ } else {
+ CPPErrorToInfoLog("ERROR___ERROR_IN_HEX_CONSTANT");
+ }
+ yylvalpp->symbol_name[len] = '\0';
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ yylvalpp->sc_int = ival;
+ return CPP_INTCONSTANT;
+ } else if (ch >= '0' && ch <= '7') { // octal integer constants
+ AlreadyComplained = 0;
+ ival = 0;
+ do {
+ yylvalpp->symbol_name[len++] = ch;
+ if (ival <= 0x1fffffff) {
+ ii = ch - '0';
+ ival = (ival << 3) | ii;
+ } else {
+ if (!AlreadyComplained)
+ CPPErrorToInfoLog("ERROR___OCT_CONST_OVERFLOW");
+ AlreadyComplained = 1;
+ }
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ } while (ch >= '0' && ch <= '7');
+ if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E')
+ return lFloatConst(yylvalpp->symbol_name, len, ch, yylvalpp);
+ yylvalpp->symbol_name[len] = '\0';
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ yylvalpp->sc_int = ival;
+ return CPP_INTCONSTANT;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ ch = '0';
+ }
+ // Fall through...
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ do {
+ if (len < MAX_SYMBOL_NAME_LEN) {
+ if (len > 0 || ch != '0') {
+ yylvalpp->symbol_name[len] = ch;
+ len++;
+ }
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ }
+ } while (ch >= '0' && ch <= '9');
+ if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') {
+ return lFloatConst(yylvalpp->symbol_name, len, ch, yylvalpp);
+ } else {
+ yylvalpp->symbol_name[len] = '\0';
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ ival = 0;
+ AlreadyComplained = 0;
+ for (ii = 0; ii < len; ii++) {
+ ch = yylvalpp->symbol_name[ii] - '0';
+ if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) {
+ if (!AlreadyComplained)
+ CPPErrorToInfoLog("ERROR___INTEGER_CONST_OVERFLOW");
+ AlreadyComplained = 1;
+ }
+ ival = ival*10 + ch;
+ }
+ yylvalpp->sc_int = ival;
+ if(ival==0)
+ strcpy(yylvalpp->symbol_name,"0");
+ return CPP_INTCONSTANT;
+ }
+ break;
+ case '-':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '-') {
+ return CPP_DEC_OP;
+ } else if (ch == '=') {
+ return CPP_SUB_ASSIGN;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '-';
+ }
+ case '+':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '+') {
+ return CPP_INC_OP;
+ } else if (ch == '=') {
+ return CPP_ADD_ASSIGN;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '+';
+ }
+ case '*':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '=') {
+ return CPP_MUL_ASSIGN;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '*';
+ }
+ case '%':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '=') {
+ return CPP_MOD_ASSIGN;
+ } else if (ch == '>'){
+ return CPP_RIGHT_BRACE;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '%';
+ }
+ case ':':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '>') {
+ return CPP_RIGHT_BRACKET;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return ':';
+ }
+ case '^':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '^') {
+ return CPP_XOR_OP;
+ } else {
+ if (ch == '=')
+ return CPP_XOR_ASSIGN;
+ else{
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '^';
+ }
+ }
+
+ case '=':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '=') {
+ return CPP_EQ_OP;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '=';
+ }
+ case '!':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '=') {
+ return CPP_NE_OP;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '!';
+ }
+ case '|':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '|') {
+ return CPP_OR_OP;
+ } else {
+ if (ch == '=')
+ return CPP_OR_ASSIGN;
+ else{
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '|';
+ }
+ }
+ case '&':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '&') {
+ return CPP_AND_OP;
+ } else {
+ if (ch == '=')
+ return CPP_AND_ASSIGN;
+ else{
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '&';
+ }
+ }
+ case '<':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '<') {
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if(ch == '=')
+ return CPP_LEFT_ASSIGN;
+ else{
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return CPP_LEFT_OP;
+ }
+ } else {
+ if (ch == '=') {
+ return CPP_LE_OP;
+ } else {
+ if (ch == '%')
+ return CPP_LEFT_BRACE;
+ else if (ch == ':')
+ return CPP_LEFT_BRACKET;
+ else{
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '<';
+ }
+ }
+ }
+ case '>':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '>') {
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if(ch == '=')
+ return CPP_RIGHT_ASSIGN;
+ else{
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return CPP_RIGHT_OP;
+ }
+ } else {
+ if (ch == '=') {
+ return CPP_GE_OP;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '>';
+ }
+ }
+ case '.':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch >= '0' && ch <= '9') {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return lFloatConst(yylvalpp->symbol_name, 0, '.', yylvalpp);
+ } else {
+ if (ch == '.') {
+ return -1; // Special EOF hack
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '.';
+ }
+ }
+ case '/':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '/') {
+ do {
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ } while (ch != '\n' && ch != EOF);
+ if (ch == EOF)
+ return -1;
+ return '\n';
+ } else if (ch == '*') {
+ int nlcount = 0;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ do {
+ while (ch != '*') {
+ if (ch == '\n') nlcount++;
+ if (ch == EOF) {
+ CPPErrorToInfoLog("ERROR___EOF_IN_COMMENT");
+ return -1;
+ }
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ }
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == EOF) {
+ CPPErrorToInfoLog("ERROR___EOF_IN_COMMENT");
+ return -1;
+ }
+ } while (ch != '/');
+ if (nlcount) {
+ return '\n';
+ }
+ // Go try it again...
+ } else if (ch == '=') {
+ return CPP_DIV_ASSIGN;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '/';
+ }
+ break;
+ case '"':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ while (ch != '"' && ch != '\n' && ch != EOF) {
+ if (ch == '\\') {
+ CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language");
+ return -1;
+ }
+ if (len < MAX_STRING_LEN) {
+ string_val[len] = ch;
+ len++;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ }
+ };
+ string_val[len] = '\0';
+ if (ch == '"') {
+ yylvalpp->sc_ident = LookUpAddString(atable, string_val);
+ return CPP_STRCONSTANT;
+ } else {
+ CPPErrorToInfoLog("ERROR___CPP_EOL_IN_STRING");
+ return ERROR_SY;
+ }
+ }
+ }
+} // byte_scan
+
+int yylex_CPP(char* buf, int maxSize)
+{
+ yystypepp yylvalpp;
+ int token = '\n';
+
+ for(;;) {
+
+ char* tokenString = 0;
+ token = cpp->currentInput->scan(cpp->currentInput, &yylvalpp);
+ if(check_EOF(token))
+ return 0;
+ if (token == '#') {
+ if (cpp->previous_token == '\n'|| cpp->previous_token == 0) {
+ token = readCPPline(&yylvalpp);
+ if(check_EOF(token))
+ return 0;
+ continue;
+ } else {
+ CPPErrorToInfoLog("preprocessor command must not be preceded by any other statement in that line");
+ return 0;
+ }
+ }
+ cpp->previous_token = token;
+ // expand macros
+ if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp.sc_ident, &yylvalpp)) {
+ cpp->pastFirstStatement = 1;
+ continue;
+ }
+
+ if (token == '\n')
+ continue;
+
+ if (token == CPP_IDENTIFIER) {
+ cpp->pastFirstStatement = 1;
+ tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident);
+ } else if (token == CPP_FLOATCONSTANT||token == CPP_INTCONSTANT){
+ cpp->pastFirstStatement = 1;
+ tokenString = yylvalpp.symbol_name;
+ } else {
+ cpp->pastFirstStatement = 1;
+ tokenString = GetStringOfAtom(atable,token);
+ }
+
+ if (tokenString) {
+ if ((signed)strlen(tokenString) >= maxSize) {
+ cpp->tokensBeforeEOF = 1;
+ return maxSize;
+ } else if (strlen(tokenString) > 0) {
+ strcpy(buf, tokenString);
+ cpp->tokensBeforeEOF = 1;
+ return (int)strlen(tokenString);
+ }
+
+ return 0;
+ }
+ }
+
+ return 0;
+} // yylex
+
+//Checks if the token just read is EOF or not.
+int check_EOF(int token)
+{
+ if(token==-1){
+ if(cpp->ifdepth >0){
+ CPPErrorToInfoLog("#endif missing!! Compilation stopped");
+ cpp->CompileError=1;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////// End of scanner.c //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/scanner.h b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/scanner.h
new file mode 100644
index 0000000..571fe57
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/scanner.h
@@ -0,0 +1,85 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// scanner.h
+//
+
+#if !defined(__SCANNER_H)
+#define __SCANNER_H 1
+
+#define MAX_SYMBOL_NAME_LEN 128
+#define MAX_STRING_LEN 512
+
+#include "compiler/preprocessor/parser.h"
+
+// Not really atom table stuff but needed first...
+
+typedef struct SourceLoc_Rec {
+ unsigned short file, line;
+} SourceLoc;
+
+int yyparse (void);
+
+int yylex_CPP(char* buf, int maxSize);
+
+typedef struct InputSrc {
+ struct InputSrc *prev;
+ int (*scan)(struct InputSrc *, yystypepp *);
+ int (*getch)(struct InputSrc *, yystypepp *);
+ void (*ungetch)(struct InputSrc *, int, yystypepp *);
+ int name; /* atom */
+ int line;
+} InputSrc;
+
+int InitScanner(CPPStruct *cpp); // Intialise the cpp scanner.
+int ScanFromString(char *); // Start scanning the input from the string mentioned.
+int check_EOF(int); // check if we hit a EOF abruptly
+void CPPErrorToInfoLog(char *); // sticking the msg,line into the Shader's.Info.log
+void SetLineNumber(int);
+void SetStringNumber(int);
+void IncLineNumber(void);
+void DecLineNumber(void);
+int FreeScanner(void); // Free the cpp scanner
+#endif // !(defined(__SCANNER_H)
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/slglobals.h b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/slglobals.h
new file mode 100644
index 0000000..4634626
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/slglobals.h
@@ -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/Source/ThirdParty/ANGLE/src/compiler/preprocessor/symbols.c b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/symbols.c
new file mode 100644
index 0000000..5baedf5
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/symbols.c
@@ -0,0 +1,284 @@
+/****************************************************************************\
+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"
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////// 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/Source/ThirdParty/ANGLE/src/compiler/preprocessor/symbols.h b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/symbols.h
new file mode 100644
index 0000000..c19f79c
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/symbols.h
@@ -0,0 +1,112 @@
+/****************************************************************************\
+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);
+void CPPErrorToInfoLog(char *);
+
+
+#endif // !defined(__SYMBOLS_H)
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/tokens.c b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/tokens.c
new file mode 100644
index 0000000..057cce8
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/tokens.c
@@ -0,0 +1,439 @@
+/****************************************************************************\
+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 "compiler/debug.h"
+#include "compiler/preprocessor/slglobals.h"
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////// Preprocessor and Token Recorder and Playback: ////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+ * idstr()
+ * Copy a string to a malloc'ed block and convert it into something suitable
+ * for an ID
+ *
+ */
+
+static char *idstr(const char *fstr, MemoryPool *pool)
+{
+ size_t len;
+ char *str, *t;
+ const char *f;
+
+ len = strlen(fstr);
+ if (!pool)
+ str = (char *) malloc(len + 1);
+ else
+ str = (char *) mem_Alloc(pool, len + 1);
+
+ for (f=fstr, t=str; *f; f++) {
+ if (isalnum(*f)) *t++ = *f;
+ else if (*f == '.' || *f == '/') *t++ = '_';
+ }
+ *t = 0;
+ return str;
+} // idstr
+
+
+/*
+ * lNewBlock()
+ *
+ */
+
+static TokenBlock *lNewBlock(TokenStream *fTok, MemoryPool *pool)
+{
+ TokenBlock *lBlock;
+
+ if (!pool)
+ lBlock = (TokenBlock *) malloc(sizeof(TokenBlock) + 256);
+ else
+ lBlock = (TokenBlock *) mem_Alloc(pool, sizeof(TokenBlock) + 256);
+ lBlock->count = 0;
+ lBlock->current = 0;
+ lBlock->data = (unsigned char *) lBlock + sizeof(TokenBlock);
+ lBlock->max = 256;
+ lBlock->next = NULL;
+ if (fTok->head) {
+ fTok->current->next = lBlock;
+ } else {
+ fTok->head = lBlock;
+ }
+ fTok->current = lBlock;
+ return lBlock;
+} // lNewBlock
+
+/*
+ * lAddByte()
+ *
+ */
+
+static void lAddByte(TokenStream *fTok, unsigned char fVal)
+{
+ TokenBlock *lBlock;
+ lBlock = fTok->current;
+ if (lBlock->count >= lBlock->max)
+ lBlock = lNewBlock(fTok, 0);
+ lBlock->data[lBlock->count++] = fVal;
+} // lAddByte
+
+
+
+/*
+ * lReadByte() - Get the next byte from a stream.
+ *
+ */
+
+static int lReadByte(TokenStream *pTok)
+{
+ TokenBlock *lBlock;
+ int lval = -1;
+
+ lBlock = pTok->current;
+ if (lBlock) {
+ if (lBlock->current >= lBlock->count) {
+ lBlock = lBlock->next;
+ if (lBlock)
+ lBlock->current = 0;
+ pTok->current = lBlock;
+ }
+ if (lBlock)
+ lval = lBlock->data[lBlock->current++];
+ }
+ return lval;
+} // lReadByte
+
+/////////////////////////////////////// Global Functions://////////////////////////////////////
+
+/*
+ * NewTokenStream()
+ *
+ */
+
+TokenStream *NewTokenStream(const char *name, MemoryPool *pool)
+{
+ TokenStream *pTok;
+
+ if (!pool)
+ pTok = (TokenStream *) malloc(sizeof(TokenStream));
+ else
+ pTok = (TokenStream*)mem_Alloc(pool, sizeof(TokenStream));
+ pTok->next = NULL;
+ pTok->name = idstr(name, pool);
+ pTok->head = NULL;
+ pTok->current = NULL;
+ lNewBlock(pTok, pool);
+ return pTok;
+} // NewTokenStream
+
+/*
+ * DeleteTokenStream()
+ *
+ */
+
+void DeleteTokenStream(TokenStream *pTok)
+{
+ TokenBlock *pBlock, *nBlock;
+
+ if (pTok) {
+ pBlock = pTok->head;
+ while (pBlock) {
+ nBlock = pBlock->next;
+ free(pBlock);
+ pBlock = nBlock;
+ }
+ if (pTok->name)
+ free(pTok->name);
+ free(pTok);
+ }
+} // DeleteTokenStream
+
+/*
+ * RecordToken() - Add a token to the end of a list for later playback or printout.
+ *
+ */
+
+void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp)
+{
+ const char *s;
+ char *str=NULL;
+
+ if (token > 256)
+ lAddByte(pTok, (unsigned char)((token & 0x7f) + 0x80));
+ else
+ lAddByte(pTok, (unsigned char)(token & 0x7f));
+ switch (token) {
+ case CPP_IDENTIFIER:
+ case CPP_TYPEIDENTIFIER:
+ case CPP_STRCONSTANT:
+ s = GetAtomString(atable, yylvalpp->sc_ident);
+ while (*s)
+ lAddByte(pTok, (unsigned char) *s++);
+ lAddByte(pTok, 0);
+ break;
+ case CPP_FLOATCONSTANT:
+ case CPP_INTCONSTANT:
+ str=yylvalpp->symbol_name;
+ while (*str){
+ lAddByte(pTok,(unsigned char) *str);
+ *str++;
+ }
+ lAddByte(pTok, 0);
+ break;
+ case '(':
+ lAddByte(pTok, (unsigned char)(yylvalpp->sc_int ? 1 : 0));
+ default:
+ break;
+ }
+} // RecordToken
+
+/*
+ * RewindTokenStream() - Reset a token stream in preperation for reading.
+ *
+ */
+
+void RewindTokenStream(TokenStream *pTok)
+{
+ if (pTok->head) {
+ pTok->current = pTok->head;
+ pTok->current->current = 0;
+ }
+} // RewindTokenStream
+
+/*
+ * ReadToken() - Read the next token from a stream.
+ *
+ */
+
+int ReadToken(TokenStream *pTok, yystypepp * yylvalpp)
+{
+ char symbol_name[MAX_SYMBOL_NAME_LEN + 1];
+ char string_val[MAX_STRING_LEN + 1];
+ int ltoken, len;
+ char ch;
+
+ ltoken = lReadByte(pTok);
+ if (ltoken >= 0) {
+ if (ltoken > 127)
+ ltoken += 128;
+ switch (ltoken) {
+ case CPP_IDENTIFIER:
+ case CPP_TYPEIDENTIFIER:
+ len = 0;
+ ch = lReadByte(pTok);
+ while ((ch >= 'a' && ch <= 'z') ||
+ (ch >= 'A' && ch <= 'Z') ||
+ (ch >= '0' && ch <= '9') ||
+ ch == '_')
+ {
+ if (len < MAX_SYMBOL_NAME_LEN) {
+ symbol_name[len] = ch;
+ len++;
+ ch = lReadByte(pTok);
+ }
+ }
+ symbol_name[len] = '\0';
+ assert(ch == '\0');
+ yylvalpp->sc_ident = LookUpAddString(atable, symbol_name);
+ return CPP_IDENTIFIER;
+ break;
+ case CPP_STRCONSTANT:
+ len = 0;
+ while ((ch = lReadByte(pTok)) != 0)
+ if (len < MAX_STRING_LEN)
+ string_val[len++] = ch;
+ string_val[len] = 0;
+ yylvalpp->sc_ident = LookUpAddString(atable, string_val);
+ break;
+ case CPP_FLOATCONSTANT:
+ len = 0;
+ ch = lReadByte(pTok);
+ while ((ch >= '0' && ch <= '9')||(ch=='e'||ch=='E'||ch=='.')||(ch=='+'||ch=='-'))
+ {
+ if (len < MAX_SYMBOL_NAME_LEN) {
+ symbol_name[len] = ch;
+ len++;
+ ch = lReadByte(pTok);
+ }
+ }
+ symbol_name[len] = '\0';
+ assert(ch == '\0');
+ strcpy(yylvalpp->symbol_name,symbol_name);
+ yylvalpp->sc_fval=(float)atof(yylvalpp->symbol_name);
+ break;
+ case CPP_INTCONSTANT:
+ len = 0;
+ ch = lReadByte(pTok);
+ while ((ch >= '0' && ch <= '9'))
+ {
+ if (len < MAX_SYMBOL_NAME_LEN) {
+ symbol_name[len] = ch;
+ len++;
+ ch = lReadByte(pTok);
+ }
+ }
+ symbol_name[len] = '\0';
+ assert(ch == '\0');
+ strcpy(yylvalpp->symbol_name,symbol_name);
+ yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+ break;
+ case '(':
+ yylvalpp->sc_int = lReadByte(pTok);
+ break;
+ }
+ return ltoken;
+ }
+ return EOF_SY;
+} // ReadToken
+
+typedef struct TokenInputSrc {
+ InputSrc base;
+ TokenStream *tokens;
+ int (*final)(CPPStruct *);
+} TokenInputSrc;
+
+static int scan_token(TokenInputSrc *in, yystypepp * yylvalpp)
+{
+ int token = ReadToken(in->tokens, yylvalpp);
+ int (*final)(CPPStruct *);
+ cpp->tokenLoc->file = cpp->currentInput->name;
+ cpp->tokenLoc->line = cpp->currentInput->line;
+ if (token == '\n') {
+ in->base.line++;
+ return token;
+ }
+ if (token > 0) return token;
+ cpp->currentInput = in->base.prev;
+ final = in->final;
+ free(in);
+ if (final && !final(cpp)) return -1;
+ return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+}
+
+int ReadFromTokenStream(TokenStream *ts, int name, int (*final)(CPPStruct *))
+{
+ TokenInputSrc *in = malloc(sizeof(TokenInputSrc));
+ memset(in, 0, sizeof(TokenInputSrc));
+ in->base.name = name;
+ in->base.prev = cpp->currentInput;
+ in->base.scan = (int (*)(InputSrc *, yystypepp *))scan_token;
+ in->base.line = 1;
+ in->tokens = ts;
+ in->final = final;
+ RewindTokenStream(ts);
+ cpp->currentInput = &in->base;
+ return 1;
+}
+
+typedef struct UngotToken {
+ InputSrc base;
+ int token;
+ yystypepp lval;
+} UngotToken;
+
+static int reget_token(UngotToken *t, yystypepp * yylvalpp)
+{
+ int token = t->token;
+ *yylvalpp = t->lval;
+ cpp->currentInput = t->base.prev;
+ free(t);
+ return token;
+}
+
+void UngetToken(int token, yystypepp * yylvalpp) {
+ UngotToken *t = malloc(sizeof(UngotToken));
+ memset(t, 0, sizeof(UngotToken));
+ t->token = token;
+ t->lval = *yylvalpp;
+ t->base.scan = (void *)reget_token;
+ t->base.prev = cpp->currentInput;
+ t->base.name = cpp->currentInput->name;
+ t->base.line = cpp->currentInput->line;
+ cpp->currentInput = &t->base;
+}
+
+
+void DumpTokenStream(FILE *fp, TokenStream *s, yystypepp * yylvalpp) {
+ int token;
+ char str[100];
+
+ if (fp == 0) fp = stdout;
+ RewindTokenStream(s);
+ while ((token = ReadToken(s, yylvalpp)) > 0) {
+ switch (token) {
+ case CPP_IDENTIFIER:
+ case CPP_TYPEIDENTIFIER:
+ sprintf(str, "%s ", GetAtomString(atable, yylvalpp->sc_ident));
+ break;
+ case CPP_STRCONSTANT:
+ sprintf(str, "\"%s\"", GetAtomString(atable, yylvalpp->sc_ident));
+ break;
+ case CPP_FLOATCONSTANT:
+ //printf("%g9.6 ", yylvalpp->sc_fval);
+ break;
+ case CPP_INTCONSTANT:
+ //printf("%d ", yylvalpp->sc_int);
+ break;
+ default:
+ if (token >= 127)
+ sprintf(str, "%s ", GetAtomString(atable, token));
+ else
+ sprintf(str, "%c", token);
+ break;
+ }
+ CPPDebugLogMsg(str);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////// End of tokens.c ///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/tokens.h b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/tokens.h
new file mode 100644
index 0000000..8766df9
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/tokens.h
@@ -0,0 +1,89 @@
+/****************************************************************************\
+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 "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/Source/ThirdParty/ANGLE/src/compiler/unistd.h b/Source/ThirdParty/ANGLE/src/compiler/unistd.h
new file mode 100644
index 0000000..c7c9147
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/compiler/unistd.h
@@ -0,0 +1 @@
+// This is a NULL file and is meant to be empty
diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Config.cpp b/Source/ThirdParty/ANGLE/src/libEGL/Config.cpp
new file mode 100644
index 0000000..21d4661
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libEGL/Config.cpp
@@ -0,0 +1,397 @@
+//
+// 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)
+ : mDisplayMode(displayMode), mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample)
+{
+ set(displayMode, minInterval, maxInterval, renderTargetFormat, depthStencilFormat, multiSample);
+}
+
+void Config::setDefaults()
+{
+ mBufferSize = 0;
+ mRedSize = 0;
+ mGreenSize = 0;
+ mBlueSize = 0;
+ mLuminanceSize = 0;
+ mAlphaSize = 0;
+ mAlphaMaskSize = 0;
+ mBindToTextureRGB = EGL_DONT_CARE;
+ mBindToTextureRGBA = EGL_DONT_CARE;
+ mColorBufferType = EGL_RGB_BUFFER;
+ mConfigCaveat = EGL_DONT_CARE;
+ mConfigID = EGL_DONT_CARE;
+ mConformant = 0;
+ mDepthSize = 0;
+ mLevel = 0;
+ mMatchNativePixmap = EGL_NONE;
+ mMaxPBufferWidth = 0;
+ mMaxPBufferHeight = 0;
+ mMaxPBufferPixels = 0;
+ mMaxSwapInterval = EGL_DONT_CARE;
+ mMinSwapInterval = EGL_DONT_CARE;
+ mNativeRenderable = EGL_DONT_CARE;
+ mNativeVisualID = 0;
+ mNativeVisualType = EGL_DONT_CARE;
+ mRenderableType = EGL_OPENGL_ES_BIT;
+ mSampleBuffers = 0;
+ mSamples = 0;
+ mStencilSize = 0;
+ mSurfaceType = EGL_WINDOW_BIT;
+ mTransparentType = EGL_NONE;
+ mTransparentRedValue = EGL_DONT_CARE;
+ mTransparentGreenValue = EGL_DONT_CARE;
+ mTransparentBlueValue = EGL_DONT_CARE;
+}
+
+void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample)
+{
+ switch (renderTargetFormat)
+ {
+ case D3DFMT_A1R5G5B5:
+ mBufferSize = 16;
+ mRedSize = 5;
+ mGreenSize = 5;
+ mBlueSize = 5;
+ mAlphaSize = 1;
+ break;
+ case D3DFMT_A2R10G10B10:
+ mBufferSize = 32;
+ mRedSize = 10;
+ mGreenSize = 10;
+ mBlueSize = 10;
+ mAlphaSize = 2;
+ break;
+ case D3DFMT_A8R8G8B8:
+ mBufferSize = 32;
+ mRedSize = 8;
+ mGreenSize = 8;
+ mBlueSize = 8;
+ mAlphaSize = 8;
+ break;
+ case D3DFMT_R5G6B5:
+ mBufferSize = 16;
+ mRedSize = 5;
+ mGreenSize = 6;
+ mBlueSize = 5;
+ mAlphaSize = 0;
+ break;
+ case D3DFMT_X1R5G5B5:
+ mBufferSize = 16;
+ mRedSize = 5;
+ mGreenSize = 5;
+ mBlueSize = 5;
+ mAlphaSize = 0;
+ break;
+ case D3DFMT_X8R8G8B8:
+ mBufferSize = 32;
+ mRedSize = 8;
+ mGreenSize = 8;
+ mBlueSize = 8;
+ mAlphaSize = 0;
+ break;
+ default:
+ UNREACHABLE(); // Other formats should not be valid
+ }
+
+ mLuminanceSize = 0;
+ mAlphaMaskSize = 0;
+ mBindToTextureRGB = EGL_FALSE;
+ mBindToTextureRGBA = EGL_FALSE;
+ mColorBufferType = EGL_RGB_BUFFER;
+ mConfigCaveat = (displayMode.Format == renderTargetFormat) ? EGL_NONE : EGL_SLOW_CONFIG;
+ mConfigID = 0;
+ mConformant = EGL_OPENGL_ES2_BIT;
+
+ switch (depthStencilFormat)
+ {
+// case D3DFMT_D16_LOCKABLE:
+// mDepthSize = 16;
+// mStencilSize = 0;
+// break;
+ case D3DFMT_D32:
+ mDepthSize = 32;
+ mStencilSize = 0;
+ break;
+ case D3DFMT_D15S1:
+ mDepthSize = 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 = 0;
+ mMaxPBufferHeight = 0;
+ mMaxPBufferPixels = 0;
+ mMaxSwapInterval = maxInterval;
+ mMinSwapInterval = minInterval;
+ mNativeRenderable = EGL_FALSE;
+ mNativeVisualID = 0;
+ mNativeVisualType = 0;
+ mRenderableType = EGL_OPENGL_ES2_BIT;
+ mSampleBuffers = multiSample ? 1 : 0;
+ mSamples = multiSample;
+ mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+ mTransparentType = EGL_NONE;
+ mTransparentRedValue = 0;
+ mTransparentGreenValue = 0;
+ mTransparentBlueValue = 0;
+}
+
+EGLConfig Config::getHandle() const
+{
+ return (EGLConfig)(size_t)mConfigID;
+}
+
+SortConfig::SortConfig(const EGLint *attribList)
+ : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
+{
+ scanForWantedComponents(attribList);
+}
+
+void SortConfig::scanForWantedComponents(const EGLint *attribList)
+{
+ // [EGL] section 3.4.1 page 24
+ // Sorting rule #3: by larger total number of color bits, not considering
+ // components that are 0 or don't-care.
+ for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
+ {
+ if (attr[1] != 0 && attr[1] != EGL_DONT_CARE)
+ {
+ switch (attr[0])
+ {
+ case EGL_RED_SIZE: mWantRed = true; break;
+ case EGL_GREEN_SIZE: mWantGreen = true; break;
+ case EGL_BLUE_SIZE: mWantBlue = true; break;
+ case EGL_ALPHA_SIZE: mWantAlpha = true; break;
+ case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
+ }
+ }
+ }
+}
+
+EGLint SortConfig::wantedComponentsSize(const Config &config) const
+{
+ EGLint total = 0;
+
+ if (mWantRed) total += config.mRedSize;
+ if (mWantGreen) total += config.mGreenSize;
+ if (mWantBlue) total += config.mBlueSize;
+ if (mWantAlpha) total += config.mAlphaSize;
+ if (mWantLuminance) total += config.mLuminanceSize;
+
+ return total;
+}
+
+bool SortConfig::operator()(const Config *x, const Config *y) const
+{
+ return (*this)(*x, *y);
+}
+
+bool SortConfig::operator()(const Config &x, const Config &y) const
+{
+ #define SORT(attribute) \
+ if (x.attribute != y.attribute) \
+ { \
+ return x.attribute < y.attribute; \
+ }
+
+ META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
+ SORT(mConfigCaveat);
+
+ META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
+ SORT(mColorBufferType);
+
+ // By larger total number of color bits, only considering those that are requested to be > 0.
+ EGLint xComponentsSize = wantedComponentsSize(x);
+ EGLint yComponentsSize = wantedComponentsSize(y);
+ if (xComponentsSize != yComponentsSize)
+ {
+ return xComponentsSize > yComponentsSize;
+ }
+
+ SORT(mBufferSize);
+ SORT(mSampleBuffers);
+ SORT(mSamples);
+ SORT(mDepthSize);
+ SORT(mStencilSize);
+ SORT(mAlphaMaskSize);
+ SORT(mNativeVisualType);
+ SORT(mConfigID);
+
+ #undef SORT
+
+ return false;
+}
+
+// We'd like to use SortConfig to also eliminate duplicate configs.
+// This works as long as we never have two configs with different per-RGB-component layouts,
+// but the same total.
+// 5551 and 565 are different because R+G+B is different.
+// 5551 and 555 are different because bufferSize is different.
+const EGLint ConfigSet::mSortAttribs[] =
+{
+ EGL_RED_SIZE, 1,
+ EGL_GREEN_SIZE, 1,
+ EGL_BLUE_SIZE, 1,
+ EGL_LUMINANCE_SIZE, 1,
+ // BUT NOT ALPHA
+ EGL_NONE
+};
+
+ConfigSet::ConfigSet()
+ : mSet(SortConfig(mSortAttribs))
+{
+}
+
+void ConfigSet::add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample)
+{
+ Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample);
+
+ mSet.insert(config);
+}
+
+size_t ConfigSet::size() const
+{
+ return mSet.size();
+}
+
+bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
+{
+ vector<const Config*> passed;
+ passed.reserve(mSet.size());
+
+ for (Iterator config = mSet.begin(); config != mSet.end(); config++)
+ {
+ bool match = true;
+ const EGLint *attribute = attribList;
+
+ while (attribute[0] != EGL_NONE)
+ {
+ switch (attribute[0])
+ {
+ case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break;
+ case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break;
+ case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break;
+ case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break;
+ case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break;
+ case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break;
+ case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break;
+ case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == attribute[1]; break;
+ case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break;
+ case EGL_LEVEL: match = config->mLevel >= attribute[1]; break;
+ case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == attribute[1]; break;
+ case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break;
+ case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break;
+ case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break;
+ case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break;
+ case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == attribute[1]; break;
+ case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break;
+ case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break;
+ case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break;
+ case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == attribute[1]; break;
+ case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == attribute[1]; break;
+ case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break;
+ case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break;
+ case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break;
+ case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break;
+ case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == attribute[1]; break;
+ case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
+ case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
+ case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break;
+ 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/Source/ThirdParty/ANGLE/src/libEGL/Config.h b/Source/ThirdParty/ANGLE/src/libEGL/Config.h
new file mode 100644
index 0000000..b340f56
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libEGL/Config.h
@@ -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);
+
+ void setDefaults();
+ void set(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample);
+ EGLConfig getHandle() const;
+
+ const D3DDISPLAYMODE mDisplayMode;
+ const D3DFORMAT mRenderTargetFormat;
+ const D3DFORMAT mDepthStencilFormat;
+ const EGLint mMultiSample;
+
+ EGLint mBufferSize; // Depth of the color buffer
+ EGLint mRedSize; // Bits of Red in the color buffer
+ EGLint mGreenSize; // Bits of Green in the color buffer
+ EGLint mBlueSize; // Bits of Blue in the color buffer
+ EGLint mLuminanceSize; // Bits of Luminance in the color buffer
+ EGLint mAlphaSize; // Bits of Alpha in the color buffer
+ EGLint mAlphaMaskSize; // Bits of Alpha Mask in the mask buffer
+ EGLBoolean mBindToTextureRGB; // True if bindable to RGB textures.
+ EGLBoolean mBindToTextureRGBA; // True if bindable to RGBA textures.
+ EGLenum mColorBufferType; // Color buffer type
+ EGLenum mConfigCaveat; // Any caveats for the configuration
+ EGLint mConfigID; // Unique EGLConfig identifier
+ EGLint mConformant; // Whether contexts created with this config are conformant
+ EGLint mDepthSize; // Bits of Z in the depth buffer
+ EGLint mLevel; // Frame buffer level
+ EGLBoolean mMatchNativePixmap; // Match the native pixmap format
+ EGLint mMaxPBufferWidth; // Maximum width of pbuffer
+ EGLint mMaxPBufferHeight; // Maximum height of pbuffer
+ EGLint mMaxPBufferPixels; // Maximum size of pbuffer
+ EGLint mMaxSwapInterval; // Maximum swap interval
+ EGLint mMinSwapInterval; // Minimum swap interval
+ EGLBoolean mNativeRenderable; // EGL_TRUE if native rendering APIs can render to surface
+ EGLint mNativeVisualID; // Handle of corresponding native visual
+ EGLint mNativeVisualType; // Native visual type of the associated visual
+ EGLint mRenderableType; // Which client rendering APIs are supported.
+ EGLint mSampleBuffers; // Number of multisample buffers
+ EGLint mSamples; // Number of samples per pixel
+ EGLint mStencilSize; // Bits of Stencil in the stencil buffer
+ EGLint mSurfaceType; // Which types of EGL surfaces are supported.
+ EGLenum mTransparentType; // Type of transparency supported
+ EGLint mTransparentRedValue; // Transparent red value
+ EGLint mTransparentGreenValue; // Transparent green value
+ EGLint mTransparentBlueValue; // Transparent blue value
+};
+
+// Function object used by STL sorting routines for ordering Configs according to [EGL] section 3.4.1 page 24.
+class SortConfig
+{
+ public:
+ explicit SortConfig(const EGLint *attribList);
+
+ bool operator()(const Config *x, const Config *y) const;
+ bool operator()(const Config &x, const Config &y) const;
+
+ private:
+ void scanForWantedComponents(const EGLint *attribList);
+ EGLint wantedComponentsSize(const Config &config) const;
+
+ bool mWantRed;
+ bool mWantGreen;
+ bool mWantBlue;
+ bool mWantAlpha;
+ bool mWantLuminance;
+};
+
+class ConfigSet
+{
+ friend Display;
+
+ public:
+ ConfigSet();
+
+ void add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample);
+ size_t size() const;
+ bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
+ const egl::Config *get(EGLConfig configHandle);
+
+ private:
+ 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/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp b/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp
new file mode 100644
index 0000000..e2802da
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp
@@ -0,0 +1,490 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Display.cpp: Implements the egl::Display class, representing the abstract
+// display on which graphics are drawn. Implements EGLDisplay.
+// [EGL 1.4] section 2.1.2 page 3.
+
+#include "libEGL/Display.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "common/debug.h"
+
+#include "libEGL/main.h"
+
+#define REF_RAST 0 // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
+
+namespace egl
+{
+Display::Display(HDC deviceContext) : mDc(deviceContext)
+{
+ mD3d9Module = NULL;
+
+ mD3d9 = NULL;
+ mD3d9ex = NULL;
+ mDevice = 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;
+ setSwapInterval(1);
+}
+
+Display::~Display()
+{
+ terminate();
+}
+
+bool Display::initialize()
+{
+ if (isInitialized())
+ {
+ return true;
+ }
+
+ mD3d9Module = LoadLibrary(TEXT("d3d9.dll"));
+ if (mD3d9Module == NULL)
+ {
+ terminate();
+ return false;
+ }
+
+ typedef IDirect3D9* (WINAPI *Direct3DCreate9Func)(UINT);
+ Direct3DCreate9Func Direct3DCreate9Ptr = reinterpret_cast<Direct3DCreate9Func>(GetProcAddress(mD3d9Module, "Direct3DCreate9"));
+
+ if (Direct3DCreate9Ptr == 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 (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9ex)))
+ {
+ ASSERT(mD3d9ex);
+ mD3d9ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
+ ASSERT(mD3d9);
+ }
+ else
+ {
+ mD3d9 = Direct3DCreate9Ptr(D3D_SDK_VERSION);
+ }
+
+ if (mD3d9)
+ {
+ if (mDc != NULL)
+ {
+ // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to
+ }
+
+ HRESULT result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
+
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+ {
+ return error(EGL_BAD_ALLOC, false);
+ }
+
+ if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 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);}
+
+ 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,
+ D3DFMT_X8R8G8B8
+ };
+
+ const D3DFORMAT depthStencilFormats[] =
+ {
+ // D3DFMT_D16_LOCKABLE,
+ D3DFMT_D32,
+ // D3DFMT_D15S1,
+ D3DFMT_D24S8,
+ D3DFMT_D24X8,
+ // D3DFMT_D24X4S4,
+ D3DFMT_D16,
+ // D3DFMT_D32F_LOCKABLE,
+ // D3DFMT_D24FS8
+ };
+
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+ 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 = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
+
+ if (SUCCEEDED(result))
+ {
+ HRESULT result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
+
+ if (SUCCEEDED(result))
+ {
+ // FIXME: enumerate multi-sampling
+
+ configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0);
+ }
+ }
+ }
+ }
+ }
+
+ // Give the sorted configs a unique ID and store them internally
+ EGLint index = 1;
+ for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++)
+ {
+ Config configuration = *config;
+ configuration.mConfigID = index;
+ index++;
+
+ mConfigSet.mSet.insert(configuration);
+ }
+
+ if (!createDevice())
+ {
+ terminate();
+
+ return false;
+ }
+ }
+
+ if (!isInitialized())
+ {
+ terminate();
+
+ return false;
+ }
+
+ return true;
+}
+
+void Display::terminate()
+{
+ for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
+ {
+ delete *surface;
+ }
+
+ for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
+ {
+ glDestroyContext(*context);
+ }
+
+ if (mDevice)
+ {
+ mDevice->Release();
+ mDevice = NULL;
+ }
+
+ if (mD3d9)
+ {
+ mD3d9->Release();
+ mD3d9 = NULL;
+ }
+
+ if (mDeviceWindow)
+ {
+ DestroyWindow(mDeviceWindow);
+ mDeviceWindow = NULL;
+ }
+
+ if (mD3d9ex)
+ {
+ mD3d9ex->Release();
+ mD3d9ex = NULL;
+ }
+
+ if (mD3d9Module)
+ {
+ FreeLibrary(mD3d9Module);
+ mD3d9Module = NULL;
+ }
+}
+
+void Display::startScene()
+{
+ if (!mSceneStarted)
+ {
+ long result = mDevice->BeginScene();
+ ASSERT(SUCCEEDED(result));
+ mSceneStarted = true;
+ }
+}
+
+void Display::endScene()
+{
+ if (mSceneStarted)
+ {
+ long result = mDevice->EndScene();
+ ASSERT(SUCCEEDED(result));
+ 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;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool Display::createDevice()
+{
+ 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);
+
+ 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 = convertInterval(mMinSwapInterval);
+ presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ presentParameters.Windowed = TRUE;
+
+ 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)
+ {
+ return error(EGL_BAD_ALLOC, false);
+ }
+
+ if (FAILED(result))
+ {
+ result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
+
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+ {
+ return error(EGL_BAD_ALLOC, false);
+ }
+ }
+
+ ASSERT(SUCCEEDED(result));
+
+ // Permanent non-default states
+ mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
+
+ mSceneStarted = false;
+
+ return true;
+}
+
+Surface *Display::createWindowSurface(HWND window, EGLConfig config)
+{
+ const Config *configuration = mConfigSet.get(config);
+
+ Surface *surface = new Surface(this, configuration, window);
+ mSurfaceSet.insert(surface);
+
+ return surface;
+}
+
+EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext)
+{
+ const egl::Config *config = mConfigSet.get(configHandle);
+
+ gl::Context *context = glCreateContext(config, shareContext);
+ mContextSet.insert(context);
+
+ return context;
+}
+
+void Display::destroySurface(egl::Surface *surface)
+{
+ delete surface;
+ mSurfaceSet.erase(surface);
+}
+
+void Display::destroyContext(gl::Context *context)
+{
+ glDestroyContext(context);
+ mContextSet.erase(context);
+}
+
+bool Display::isInitialized()
+{
+ return mD3d9 != NULL && mConfigSet.size() > 0;
+}
+
+bool Display::isValidConfig(EGLConfig config)
+{
+ return mConfigSet.get(config) != NULL;
+}
+
+bool Display::isValidContext(gl::Context *context)
+{
+ return mContextSet.find(context) != mContextSet.end();
+}
+
+bool Display::isValidSurface(egl::Surface *surface)
+{
+ return mSurfaceSet.find(surface) != mSurfaceSet.end();
+}
+
+bool Display::hasExistingWindowSurface(HWND window)
+{
+ for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
+ {
+ if ((*surface)->getWindowHandle() == window)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void Display::setSwapInterval(GLint interval)
+{
+ mSwapInterval = interval;
+ mSwapInterval = std::max(mSwapInterval, mMinSwapInterval);
+ mSwapInterval = std::min(mSwapInterval, mMaxSwapInterval);
+
+ mPresentInterval = convertInterval(mSwapInterval);
+}
+
+DWORD Display::getPresentInterval()
+{
+ return mPresentInterval;
+}
+
+DWORD Display::convertInterval(GLint 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;
+}
+
+IDirect3DDevice9 *Display::getDevice()
+{
+ return mDevice;
+}
+
+D3DCAPS9 Display::getDeviceCaps()
+{
+ return mDeviceCaps;
+}
+
+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::getCompressedTextureSupport()
+{
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+ return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
+}
+}
diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Display.h b/Source/ThirdParty/ANGLE/src/libEGL/Display.h
new file mode 100644
index 0000000..bd33012
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libEGL/Display.h
@@ -0,0 +1,98 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Display.h: Defines the egl::Display class, representing the abstract
+// display on which graphics are drawn. Implements EGLDisplay.
+// [EGL 1.4] section 2.1.2 page 3.
+
+#ifndef INCLUDE_DISPLAY_H_
+#define INCLUDE_DISPLAY_H_
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <d3d9.h>
+
+#include <set>
+
+#include "libGLESv2/Context.h"
+
+#include "libEGL/Config.h"
+#include "libEGL/Surface.h"
+
+namespace egl
+{
+class Display
+{
+ public:
+ Display(HDC deviceContext);
+
+ ~Display();
+
+ bool initialize();
+ void terminate();
+
+ virtual void startScene();
+ virtual void endScene();
+
+ bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
+ bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);
+
+ egl::Surface *createWindowSurface(HWND window, EGLConfig config);
+ EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext);
+
+ void destroySurface(egl::Surface *surface);
+ void destroyContext(gl::Context *context);
+
+ bool isInitialized();
+ bool isValidConfig(EGLConfig config);
+ bool isValidContext(gl::Context *context);
+ bool isValidSurface(egl::Surface *surface);
+ bool hasExistingWindowSurface(HWND window);
+
+ void setSwapInterval(GLint interval);
+ DWORD getPresentInterval();
+ static DWORD convertInterval(GLint interval);
+
+ virtual IDirect3DDevice9 *getDevice();
+ virtual D3DCAPS9 getDeviceCaps();
+ virtual void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray);
+ virtual bool getCompressedTextureSupport();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Display);
+ 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;
+ D3DCAPS9 mDeviceCaps;
+ HWND mDeviceWindow;
+
+ bool mSceneStarted;
+ GLint mSwapInterval;
+ EGLint mMaxSwapInterval;
+ EGLint mMinSwapInterval;
+ DWORD mPresentInterval;
+
+ typedef std::set<Surface*> SurfaceSet;
+ SurfaceSet mSurfaceSet;
+
+ ConfigSet mConfigSet;
+
+ typedef std::set<gl::Context*> ContextSet;
+ ContextSet mContextSet;
+
+ bool createDevice();
+};
+}
+
+#endif // INCLUDE_DISPLAY_H_
diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp b/Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp
new file mode 100644
index 0000000..a5638d4
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp
@@ -0,0 +1,431 @@
+//
+// 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 "libEGL/Surface.h"
+
+#include "common/debug.h"
+
+#include "libEGL/main.h"
+#include "libEGL/Display.h"
+
+namespace egl
+{
+Surface::Surface(Display *display, const Config *config, HWND window)
+ : mDisplay(display), mConfig(config), mWindow(window)
+{
+ mSwapChain = NULL;
+ mDepthStencil = NULL;
+ mBackBuffer = NULL;
+ mRenderTarget = NULL;
+ mFlipTexture = NULL;
+ mFlipState = NULL;
+ mPreFlipState = NULL;
+
+ mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio
+ mRenderBuffer = EGL_BACK_BUFFER;
+ mSwapBehavior = EGL_BUFFER_PRESERVED;
+
+ resetSwapChain();
+}
+
+Surface::~Surface()
+{
+ if (mSwapChain)
+ {
+ mSwapChain->Release();
+ }
+
+ if (mBackBuffer)
+ {
+ mBackBuffer->Release();
+ }
+
+ if (mRenderTarget)
+ {
+ mRenderTarget->Release();
+ }
+
+ if (mDepthStencil)
+ {
+ mDepthStencil->Release();
+ }
+
+ if (mFlipTexture)
+ {
+ mFlipTexture->Release();
+ }
+
+ if (mFlipState)
+ {
+ mFlipState->Release();
+ }
+
+ if (mPreFlipState)
+ {
+ mPreFlipState->Release();
+ }
+}
+
+void Surface::resetSwapChain()
+{
+ IDirect3DDevice9 *device = mDisplay->getDevice();
+
+ 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 = Display::convertInterval(mConfig->mMinSwapInterval);
+ presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ presentParameters.Windowed = TRUE;
+
+ RECT windowRect;
+ if (!GetClientRect(getWindowHandle(), &windowRect))
+ {
+ ASSERT(false);
+ return;
+ }
+
+ presentParameters.BackBufferWidth = windowRect.right - windowRect.left;
+ presentParameters.BackBufferHeight = windowRect.bottom - windowRect.top;
+
+ IDirect3DSwapChain9 *swapChain = NULL;
+ HRESULT result = device->CreateAdditionalSwapChain(&presentParameters, &swapChain);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+
+ ERR("Could not create additional swap chains: %08lX", result);
+ return error(EGL_BAD_ALLOC);
+ }
+
+ IDirect3DSurface9 *depthStencilSurface = NULL;
+ result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight,
+ presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType,
+ presentParameters.MultiSampleQuality, FALSE, &depthStencilSurface, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+
+ swapChain->Release();
+
+ ERR("Could not create depthstencil surface for new swap chain: %08lX", result);
+ return error(EGL_BAD_ALLOC);
+ }
+
+ IDirect3DSurface9 *renderTarget = NULL;
+ result = device->CreateRenderTarget(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, presentParameters.BackBufferFormat,
+ presentParameters.MultiSampleType, presentParameters.MultiSampleQuality, FALSE, &renderTarget, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+
+ swapChain->Release();
+ depthStencilSurface->Release();
+
+ ERR("Could not create render target surface for new swap chain: %08lX", result);
+ return error(EGL_BAD_ALLOC);
+ }
+
+ ASSERT(SUCCEEDED(result));
+
+ IDirect3DTexture9 *flipTexture = NULL;
+ result = device->CreateTexture(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET,
+ presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &flipTexture, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+
+ swapChain->Release();
+ depthStencilSurface->Release();
+ renderTarget->Release();
+
+ ERR("Could not create flip texture for new swap chain: %08lX", result);
+ return error(EGL_BAD_ALLOC);
+ }
+
+ IDirect3DSurface9 *backBuffer = NULL;
+ swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
+
+ if (mSwapChain) mSwapChain->Release();
+ if (mDepthStencil) mDepthStencil->Release();
+ if (mBackBuffer) mBackBuffer->Release();
+ if (mRenderTarget) mRenderTarget->Release();
+ if (mFlipTexture) mFlipTexture->Release();
+
+ mWidth = presentParameters.BackBufferWidth;
+ mHeight = presentParameters.BackBufferHeight;
+
+ mSwapChain = swapChain;
+ mDepthStencil = depthStencilSurface;
+ mBackBuffer = backBuffer;
+ mRenderTarget = renderTarget;
+ mFlipTexture = flipTexture;
+
+ // The flip state block recorded mFlipTexture so it is now invalid.
+ releaseRecordedState(device);
+}
+
+HWND Surface::getWindowHandle()
+{
+ return mWindow;
+}
+
+void Surface::writeRecordableFlipState(IDirect3DDevice9 *device)
+{
+ // Disable all pipeline operations
+ device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
+ device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+ device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+ device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+ device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
+ device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
+ device->SetPixelShader(NULL);
+ device->SetVertexShader(NULL);
+
+ // Just sample the texture
+ device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ device->SetTexture(0, NULL); // The actual texture will change after resizing. But the pre-flip state block must save/restore the texture.
+ 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);
+ device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
+
+ device->SetStreamSourceFreq(0, 1); // DrawPrimitiveUP only cares about stream 0, not the rest.
+}
+
+void Surface::applyFlipState(IDirect3DDevice9 *device)
+{
+ HRESULT hr;
+
+ if (mFlipState == NULL)
+ {
+ // Create two state blocks both recording the states that are changed when swapping.
+
+ // mPreFlipState will record the original state each entry.
+ hr = device->BeginStateBlock();
+ ASSERT(SUCCEEDED(hr));
+ writeRecordableFlipState(device);
+ hr = device->EndStateBlock(&mPreFlipState);
+ ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+
+ if (SUCCEEDED(hr))
+ {
+ mPreFlipState->Capture();
+ }
+
+ // mFlipState will record the state for the swap operation.
+ hr = device->BeginStateBlock();
+ ASSERT(SUCCEEDED(hr));
+
+ writeRecordableFlipState(device);
+
+ hr = device->EndStateBlock(&mFlipState);
+ ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+
+ if (FAILED(hr))
+ {
+ mFlipState = NULL;
+ mPreFlipState->Release();
+ mPreFlipState = NULL;
+ }
+ else
+ {
+ hr = mFlipState->Apply();
+ ASSERT(SUCCEEDED(hr));
+ }
+ }
+ else
+ {
+ hr = mPreFlipState->Capture();
+ ASSERT(SUCCEEDED(hr));
+ hr = mFlipState->Apply();
+ ASSERT(SUCCEEDED(hr));
+ }
+
+ device->GetRenderTarget(0, &mPreFlipBackBuffer);
+ device->GetDepthStencilSurface(&mPreFlipDepthStencil);
+
+ device->SetRenderTarget(0, mBackBuffer);
+ device->SetDepthStencilSurface(NULL);
+}
+
+void Surface::restoreState(IDirect3DDevice9 *device)
+{
+ mPreFlipState->Apply();
+
+ device->SetRenderTarget(0, mPreFlipBackBuffer);
+ device->SetDepthStencilSurface(mPreFlipDepthStencil);
+
+ if (mPreFlipBackBuffer)
+ {
+ mPreFlipBackBuffer->Release();
+ mPreFlipBackBuffer = NULL;
+ }
+
+ if (mPreFlipDepthStencil)
+ {
+ mPreFlipDepthStencil->Release();
+ mPreFlipDepthStencil = NULL;
+ }
+}
+
+// On the next flip, this will cause the state to be recorded from scratch.
+// In particular we need to do this if the flip texture changes.
+void Surface::releaseRecordedState(IDirect3DDevice9 *device)
+{
+ if (mFlipState)
+ {
+ mFlipState->Release();
+ mFlipState = NULL;
+ }
+
+ if (mPreFlipState)
+ {
+ mPreFlipState->Release();
+ mPreFlipState = NULL;
+ }
+}
+
+bool Surface::checkForWindowResize()
+{
+ RECT client;
+ if (!GetClientRect(getWindowHandle(), &client))
+ {
+ ASSERT(false);
+ return false;
+ }
+
+ if (getWidth() != client.right - client.left || getHeight() != client.bottom - client.top)
+ {
+ resetSwapChain();
+
+ if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this)
+ {
+ glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+bool Surface::swap()
+{
+ if (mSwapChain)
+ {
+ IDirect3DTexture9 *flipTexture = mFlipTexture;
+ flipTexture->AddRef();
+
+ IDirect3DSurface9 *renderTarget = mRenderTarget;
+ renderTarget->AddRef();
+
+ EGLint oldWidth = mWidth;
+ EGLint oldHeight = mHeight;
+
+ checkForWindowResize();
+
+ IDirect3DDevice9 *device = mDisplay->getDevice();
+
+ IDirect3DSurface9 *textureSurface;
+ flipTexture->GetSurfaceLevel(0, &textureSurface);
+
+ mDisplay->endScene();
+ device->StretchRect(renderTarget, NULL, textureSurface, NULL, D3DTEXF_NONE);
+ renderTarget->Release();
+
+ applyFlipState(device);
+ device->SetTexture(0, flipTexture);
+
+ float xscale = (float)mWidth / oldWidth;
+ float yscale = (float)mHeight / oldHeight;
+
+ // Render the texture upside down into the back buffer
+ // Texcoords are chosen to pin a potentially resized image into the upper-left corner without scaling.
+ float quad[4][6] = {{ 0 - 0.5f, 0 - 0.5f, 0.0f, 1.0f, 0.0f, 1.0f },
+ {mWidth - 0.5f, 0 - 0.5f, 0.0f, 1.0f, xscale, 1.0f },
+ {mWidth - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, xscale, 1.0f-yscale},
+ { 0 - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, 0.0f, 1.0f-yscale}}; // x, y, z, rhw, u, v
+
+ mDisplay->startScene();
+ device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
+
+ flipTexture->Release();
+ textureSurface->Release();
+
+ restoreState(device);
+
+ mDisplay->endScene();
+ HRESULT result = mSwapChain->Present(NULL, NULL, NULL, NULL, mDisplay->getPresentInterval());
+
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
+ {
+ return error(EGL_BAD_ALLOC, false);
+ }
+
+ if (result == D3DERR_DEVICELOST)
+ {
+ return error(EGL_CONTEXT_LOST, false);
+ }
+
+ ASSERT(SUCCEEDED(result));
+
+ }
+
+ return true;
+}
+
+EGLint Surface::getWidth() const
+{
+ return mWidth;
+}
+
+EGLint Surface::getHeight() const
+{
+ return mHeight;
+}
+
+IDirect3DSurface9 *Surface::getRenderTarget()
+{
+ if (mRenderTarget)
+ {
+ mRenderTarget->AddRef();
+ }
+
+ return mRenderTarget;
+}
+
+IDirect3DSurface9 *Surface::getDepthStencil()
+{
+ if (mDepthStencil)
+ {
+ mDepthStencil->AddRef();
+ }
+
+ return mDepthStencil;
+}
+}
diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Surface.h b/Source/ThirdParty/ANGLE/src/libEGL/Surface.h
new file mode 100644
index 0000000..5bc912c
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libEGL/Surface.h
@@ -0,0 +1,83 @@
+//
+// 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 egl
+{
+class Display;
+class Config;
+
+class Surface
+{
+ public:
+ Surface(Display *display, const egl::Config *config, HWND window);
+
+ ~Surface();
+
+ HWND getWindowHandle();
+ bool swap();
+
+ virtual EGLint getWidth() const;
+ virtual EGLint getHeight() const;
+
+ virtual IDirect3DSurface9 *getRenderTarget();
+ virtual IDirect3DSurface9 *getDepthStencil();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Surface);
+
+ Display *const mDisplay;
+ IDirect3DSwapChain9 *mSwapChain;
+ IDirect3DSurface9 *mBackBuffer;
+ IDirect3DSurface9 *mRenderTarget;
+ IDirect3DSurface9 *mDepthStencil;
+ IDirect3DTexture9 *mFlipTexture;
+
+ void resetSwapChain();
+ bool checkForWindowResize();
+
+ void applyFlipState(IDirect3DDevice9 *device);
+ void restoreState(IDirect3DDevice9 *device);
+ void writeRecordableFlipState(IDirect3DDevice9 *device);
+ void releaseRecordedState(IDirect3DDevice9 *device);
+ IDirect3DStateBlock9 *mFlipState;
+ IDirect3DStateBlock9 *mPreFlipState;
+ IDirect3DSurface9 *mPreFlipBackBuffer;
+ IDirect3DSurface9 *mPreFlipDepthStencil;
+
+ const HWND mWindow; // Window that the surface is created for.
+ 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 textureFormat; // Format of texture: RGB, RGBA, or no texture
+// EGLenum textureTarget; // Type of texture: 2D or no texture
+// EGLenum vgAlphaFormat; // Alpha format for OpenVG
+// EGLenum vgColorSpace; // Color space for OpenVG
+};
+}
+
+#endif // INCLUDE_SURFACE_H_
diff --git a/Source/ThirdParty/ANGLE/src/libEGL/libEGL.cpp b/Source/ThirdParty/ANGLE/src/libEGL/libEGL.cpp
new file mode 100644
index 0000000..5ceb6ef
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libEGL/libEGL.cpp
@@ -0,0 +1,1084 @@
+//
+// 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 "libGLESv2/Context.h"
+
+#include "libEGL/main.h"
+#include "libEGL/Display.h"
+
+
+bool validate(egl::Display *display)
+{
+ if (display == EGL_NO_DISPLAY)
+ {
+ return error(EGL_BAD_DISPLAY, false);
+ }
+
+ if (!display->isInitialized())
+ {
+ return error(EGL_NOT_INITIALIZED, false);
+ }
+
+ return true;
+}
+
+bool validate(egl::Display *display, EGLConfig config)
+{
+ if (!validate(display))
+ {
+ return false;
+ }
+
+ if (!display->isValidConfig(config))
+ {
+ return error(EGL_BAD_CONFIG, false);
+ }
+
+ return true;
+}
+
+bool validate(egl::Display *display, gl::Context *context)
+{
+ if (!validate(display))
+ {
+ return false;
+ }
+
+ if (!display->isValidContext(context))
+ {
+ return error(EGL_BAD_CONTEXT, false);
+ }
+
+ return true;
+}
+
+bool validate(egl::Display *display, egl::Surface *surface)
+{
+ if (!validate(display))
+ {
+ return false;
+ }
+
+ if (!display->isValidSurface(surface))
+ {
+ return error(EGL_BAD_SURFACE, false);
+ }
+
+ return true;
+}
+
+extern "C"
+{
+EGLint __stdcall eglGetError(void)
+{
+ TRACE("()");
+
+ EGLint error = egl::getCurrentError();
+
+ if (error != EGL_SUCCESS)
+ {
+ egl::setCurrentError(EGL_SUCCESS);
+ }
+
+ return error;
+}
+
+EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id)
+{
+ TRACE("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id);
+
+ try
+ {
+ // FIXME: Return the same EGLDisplay handle when display_id already created a display
+
+ if (display_id == EGL_DEFAULT_DISPLAY)
+ {
+ return new egl::Display((HDC)NULL);
+ }
+ else
+ {
+ // FIXME: Check if display_id is a valid display device context
+
+ return new egl::Display((HDC)display_id);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_DISPLAY);
+ }
+
+ return EGL_NO_DISPLAY;
+}
+
+EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)",
+ dpy, major, minor);
+
+ try
+ {
+ if (dpy == EGL_NO_DISPLAY)
+ {
+ return error(EGL_BAD_DISPLAY, EGL_FALSE);
+ }
+
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!display->initialize())
+ {
+ return error(EGL_NOT_INITIALIZED, EGL_FALSE);
+ }
+
+ if (major) *major = 1;
+ if (minor) *minor = 4;
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLBoolean __stdcall eglTerminate(EGLDisplay dpy)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p)", dpy);
+
+ try
+ {
+ if (dpy == EGL_NO_DISPLAY)
+ {
+ return error(EGL_BAD_DISPLAY, EGL_FALSE);
+ }
+
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ display->terminate();
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display))
+ {
+ return NULL;
+ }
+
+ switch (name)
+ {
+ case EGL_CLIENT_APIS:
+ return success("OpenGL_ES");
+ case EGL_EXTENSIONS:
+ return success("");
+ case EGL_VENDOR:
+ return success("TransGaming Inc.");
+ case EGL_VERSION:
+ return success("1.4 (git-devel "__DATE__" " __TIME__")");
+ }
+
+ return error(EGL_BAD_PARAMETER, (const char*)NULL);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, (const char*)NULL);
+ }
+
+ return NULL;
+}
+
+EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, "
+ "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
+ dpy, configs, config_size, num_config);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display))
+ {
+ return EGL_FALSE;
+ }
+
+ if (!num_config)
+ {
+ return error(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
+ const EGLint attribList[] = {EGL_NONE};
+
+ if (!display->getConfigs(configs, attribList, config_size, num_config))
+ {
+ return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ }
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, "
+ "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
+ dpy, attrib_list, configs, config_size, num_config);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display))
+ {
+ return EGL_FALSE;
+ }
+
+ if (!num_config)
+ {
+ return error(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
+ const EGLint attribList[] = {EGL_NONE};
+
+ if (!attrib_list)
+ {
+ attrib_list = attribList;
+ }
+
+ display->getConfigs(configs, attrib_list, config_size, num_config);
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
+ dpy, config, attribute, value);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display, config))
+ {
+ return EGL_FALSE;
+ }
+
+ if (!display->getConfigAttrib(config, attribute, value))
+ {
+ return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ }
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, "
+ "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display, config))
+ {
+ return EGL_NO_SURFACE;
+ }
+
+ HWND window = (HWND)win;
+
+ if (!IsWindow(window))
+ {
+ return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+ }
+
+ if (attrib_list)
+ {
+ while (*attrib_list != EGL_NONE)
+ {
+ switch (attrib_list[0])
+ {
+ case EGL_RENDER_BUFFER:
+ switch (attrib_list[1])
+ {
+ case EGL_BACK_BUFFER:
+ break;
+ case EGL_SINGLE_BUFFER:
+ return error(EGL_BAD_MATCH, EGL_NO_SURFACE); // Rendering directly to front buffer not supported
+ default:
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ }
+ break;
+ case EGL_VG_COLORSPACE:
+ return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ case EGL_VG_ALPHA_FORMAT:
+ return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ default:
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ }
+ }
+ }
+
+ if (display->hasExistingWindowSurface(window))
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ }
+
+ EGLSurface surface = (EGLSurface)display->createWindowSurface(window, config);
+
+ return success(surface);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ }
+
+ return EGL_NO_SURFACE;
+}
+
+EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
+ dpy, config, attrib_list);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display, config))
+ {
+ return EGL_NO_SURFACE;
+ }
+
+ UNIMPLEMENTED(); // FIXME
+
+ return success(EGL_NO_DISPLAY);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ }
+
+ return EGL_NO_SURFACE;
+}
+
+EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, "
+ "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display, config))
+ {
+ return EGL_NO_SURFACE;
+ }
+
+ UNIMPLEMENTED(); // FIXME
+
+ return success(EGL_NO_DISPLAY);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ }
+
+ return EGL_NO_SURFACE;
+}
+
+EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display))
+ {
+ return EGL_FALSE;
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ return error(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ display->destroySurface((egl::Surface*)surface);
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
+ dpy, surface, attribute, value);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display))
+ {
+ return EGL_FALSE;
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ return error(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ egl::Surface *eglSurface = (egl::Surface*)surface;
+
+ switch (attribute)
+ {
+ case EGL_VG_ALPHA_FORMAT:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_VG_COLORSPACE:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_CONFIG_ID:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_HEIGHT:
+ *value = eglSurface->getHeight();
+ break;
+ case EGL_HORIZONTAL_RESOLUTION:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_LARGEST_PBUFFER:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_MIPMAP_TEXTURE:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_MIPMAP_LEVEL:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_MULTISAMPLE_RESOLVE:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_PIXEL_ASPECT_RATIO:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_RENDER_BUFFER:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_SWAP_BEHAVIOR:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_TEXTURE_FORMAT:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_TEXTURE_TARGET:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_VERTICAL_RESOLUTION:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_WIDTH:
+ *value = eglSurface->getWidth();
+ break;
+ default:
+ return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ }
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLBoolean __stdcall eglBindAPI(EGLenum api)
+{
+ TRACE("(EGLenum api = 0x%X)", api);
+
+ try
+ {
+ switch (api)
+ {
+ case EGL_OPENGL_API:
+ case EGL_OPENVG_API:
+ return error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation
+ case EGL_OPENGL_ES_API:
+ break;
+ default:
+ return error(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
+ egl::setCurrentAPI(api);
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLenum __stdcall eglQueryAPI(void)
+{
+ TRACE("()");
+
+ try
+ {
+ EGLenum API = egl::getCurrentAPI();
+
+ return success(API);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLBoolean __stdcall eglWaitClient(void)
+{
+ TRACE("()");
+
+ try
+ {
+ UNIMPLEMENTED(); // FIXME
+
+ return success(0);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLBoolean __stdcall eglReleaseThread(void)
+{
+ TRACE("()");
+
+ try
+ {
+ eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, "
+ "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
+ dpy, buftype, buffer, config, attrib_list);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display, config))
+ {
+ return EGL_NO_SURFACE;
+ }
+
+ UNIMPLEMENTED(); // FIXME
+
+ return success(EGL_NO_SURFACE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ }
+
+ return EGL_NO_SURFACE;
+}
+
+EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)",
+ dpy, surface, attribute, value);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display))
+ {
+ return EGL_FALSE;
+ }
+
+ UNIMPLEMENTED(); // FIXME
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display))
+ {
+ return EGL_FALSE;
+ }
+
+ UNIMPLEMENTED(); // FIXME
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display))
+ {
+ return EGL_FALSE;
+ }
+
+ UNIMPLEMENTED(); // FIXME
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display))
+ {
+ return EGL_FALSE;
+ }
+
+ display->setSwapInterval(interval);
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, "
+ "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display, config))
+ {
+ return EGL_NO_CONTEXT;
+ }
+
+ EGLContext context = display->createContext(config, static_cast<gl::Context*>(share_context));
+
+ return success(context);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
+ }
+
+ return EGL_NO_CONTEXT;
+}
+
+EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display))
+ {
+ return EGL_FALSE;
+ }
+
+ if (ctx == EGL_NO_CONTEXT)
+ {
+ return error(EGL_BAD_CONTEXT, EGL_FALSE);
+ }
+
+ display->destroyContext((gl::Context*)ctx);
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)",
+ dpy, draw, read, ctx);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+ gl::Context *context = static_cast<gl::Context*>(ctx);
+ IDirect3DDevice9 *device = display->getDevice();
+
+ if (!device || device->TestCooperativeLevel() != D3D_OK)
+ {
+ return error(EGL_CONTEXT_LOST, EGL_FALSE);
+ }
+
+ if (ctx != EGL_NO_CONTEXT && !validate(display, context))
+ {
+ return EGL_FALSE;
+ }
+
+ if ((draw != EGL_NO_SURFACE && !validate(display, static_cast<egl::Surface*>(draw))) ||
+ (read != EGL_NO_SURFACE && !validate(display, static_cast<egl::Surface*>(read))))
+ {
+ return EGL_FALSE;
+ }
+
+ if (draw != read)
+ {
+ UNIMPLEMENTED(); // FIXME
+ }
+
+ 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);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLContext __stdcall eglGetCurrentContext(void)
+{
+ TRACE("()");
+
+ try
+ {
+ EGLContext context = glGetCurrentContext();
+
+ return success(context);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
+ }
+
+ return EGL_NO_CONTEXT;
+}
+
+EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw)
+{
+ TRACE("(EGLint readdraw = %d)", readdraw);
+
+ try
+ {
+ if (readdraw == EGL_READ)
+ {
+ EGLSurface read = egl::getCurrentReadSurface();
+ return success(read);
+ }
+ else if (readdraw == EGL_DRAW)
+ {
+ EGLSurface draw = egl::getCurrentDrawSurface();
+ return success(draw);
+ }
+ else
+ {
+ return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ }
+
+ return EGL_NO_SURFACE;
+}
+
+EGLDisplay __stdcall eglGetCurrentDisplay(void)
+{
+ TRACE("()");
+
+ try
+ {
+ EGLDisplay dpy = egl::getCurrentDisplay();
+
+ return success(dpy);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_NO_DISPLAY);
+ }
+
+ return EGL_NO_DISPLAY;
+}
+
+EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
+ dpy, ctx, attribute, value);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display))
+ {
+ return EGL_FALSE;
+ }
+
+ UNIMPLEMENTED(); // FIXME
+
+ return success(0);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLBoolean __stdcall eglWaitGL(void)
+{
+ TRACE("()");
+
+ try
+ {
+ UNIMPLEMENTED(); // FIXME
+
+ return success(0);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLBoolean __stdcall eglWaitNative(EGLint engine)
+{
+ TRACE("(EGLint engine = %d)", engine);
+
+ try
+ {
+ UNIMPLEMENTED(); // FIXME
+
+ return success(0);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display))
+ {
+ return EGL_FALSE;
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ return error(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ egl::Surface *eglSurface = (egl::Surface*)surface;
+
+ 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)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display))
+ {
+ return EGL_FALSE;
+ }
+
+ UNIMPLEMENTED(); // FIXME
+
+ return success(0);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
+__eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname)
+{
+ TRACE("(const char *procname = \"%s\")", procname);
+
+ try
+ {
+ struct Extension
+ {
+ const char *name;
+ __eglMustCastToProperFunctionPointerType address;
+ };
+
+ static const Extension eglExtensions[] =
+ {
+ {"", NULL},
+ };
+
+ for (int ext = 0; ext < sizeof(eglExtensions) / sizeof(Extension); ext++)
+ {
+ if (strcmp(procname, eglExtensions[ext].name) == 0)
+ {
+ return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address;
+ }
+ }
+
+ return glGetProcAddress(procname);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, (__eglMustCastToProperFunctionPointerType)NULL);
+ }
+
+ return NULL;
+}
+}
diff --git a/Source/ThirdParty/ANGLE/src/libEGL/libEGL.def b/Source/ThirdParty/ANGLE/src/libEGL/libEGL.def
new file mode 100644
index 0000000..71a5e67
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libEGL/libEGL.def
@@ -0,0 +1,36 @@
+LIBRARY libEGL
+EXPORTS
+ eglBindAPI @14
+ eglBindTexImage @20
+ eglChooseConfig @7
+ eglCopyBuffers @33
+ eglCreateContext @23
+ eglCreatePbufferFromClientBuffer @18
+ eglCreatePbufferSurface @10
+ eglCreatePixmapSurface @11
+ eglCreateWindowSurface @9
+ eglDestroyContext @24
+ eglDestroySurface @12
+ eglGetConfigAttrib @8
+ eglGetConfigs @6
+ eglGetCurrentContext @26
+ eglGetCurrentDisplay @28
+ eglGetCurrentSurface @27
+ eglGetDisplay @2
+ eglGetError @1
+ eglGetProcAddress @34
+ eglInitialize @3
+ eglMakeCurrent @25
+ eglQueryAPI @15
+ eglQueryContext @29
+ eglQueryString @5
+ eglQuerySurface @13
+ eglReleaseTexImage @21
+ eglReleaseThread @17
+ eglSurfaceAttrib @19
+ eglSwapBuffers @32
+ eglSwapInterval @22
+ eglTerminate @4
+ eglWaitClient @16
+ eglWaitGL @30
+ eglWaitNative @31 \ No newline at end of file
diff --git a/Source/ThirdParty/ANGLE/src/libEGL/libEGL.vcproj b/Source/ThirdParty/ANGLE/src/libEGL/libEGL.vcproj
new file mode 100644
index 0000000..4f8d0b2
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libEGL/libEGL.vcproj
@@ -0,0 +1,252 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="libEGL"
+ ProjectGUID="{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}"
+ RootNamespace="libEGL"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(ProjectDir)/..; $(ProjectDir)/../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBEGL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="dxguid.lib"
+ LinkIncremental="2"
+ ModuleDefinitionFile="libEGL.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="@echo on&#x0D;&#x0A;mkdir &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;copy &quot;$(OutDir)\libEGL.dll&quot; &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;copy &quot;$(OutDir)\libEGL.lib&quot; &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;@echo off&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="2"
+ AdditionalIncludeDirectories="$(ProjectDir)/..; $(ProjectDir)/../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBEGL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="dxguid.lib"
+ LinkIncremental="1"
+ ModuleDefinitionFile="libEGL.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="@echo on&#x0D;&#x0A;mkdir &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;copy &quot;$(OutDir)\libEGL.dll&quot; &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;copy &quot;$(OutDir)\libEGL.lib&quot; &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;@echo off&#x0D;&#x0A;"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\Config.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Common\debug.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Display.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libEGL.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\main.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Surface.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\Config.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Display.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\EGL\egl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\EGL\eglext.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\EGL\eglplatform.h"
+ >
+ </File>
+ <File
+ RelativePath=".\main.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Surface.h"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\libEGL.def"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/ThirdParty/ANGLE/src/libEGL/main.cpp b/Source/ThirdParty/ANGLE/src/libEGL/main.cpp
new file mode 100644
index 0000000..d9902d2
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libEGL/main.cpp
@@ -0,0 +1,161 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// main.cpp: DLL entry point and management of thread-local data.
+
+#include "libEGL/main.h"
+
+#include "common/debug.h"
+
+static DWORD currentTLS = TLS_OUT_OF_INDEXES;
+
+BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
+{
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ #ifndef NDEBUG
+ FILE *debug = fopen("debug.txt", "rt");
+
+ if (debug)
+ {
+ fclose(debug);
+ debug = fopen("debug.txt", "wt"); // Erase
+ fclose(debug);
+ }
+ #endif
+
+ currentTLS = TlsAlloc();
+
+ if (currentTLS == TLS_OUT_OF_INDEXES)
+ {
+ return FALSE;
+ }
+ }
+ // Fall throught to initialize index
+ case DLL_THREAD_ATTACH:
+ {
+ egl::Current *current = (egl::Current*)LocalAlloc(LPTR, sizeof(egl::Current));
+
+ if (current)
+ {
+ TlsSetValue(currentTLS, current);
+
+ current->error = EGL_SUCCESS;
+ current->API = EGL_OPENGL_ES_API;
+ 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/Source/ThirdParty/ANGLE/src/libEGL/main.h b/Source/ThirdParty/ANGLE/src/libEGL/main.h
new file mode 100644
index 0000000..d6dc759
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libEGL/main.h
@@ -0,0 +1,60 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// main.h: Management of thread-local data.
+
+#ifndef LIBEGL_MAIN_H_
+#define LIBEGL_MAIN_H_
+
+#define EGLAPI
+#include <EGL/egl.h>
+
+namespace egl
+{
+struct Current
+{
+ EGLint error;
+ EGLenum API;
+ 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/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.cpp
new file mode 100644
index 0000000..00c878f
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.cpp
@@ -0,0 +1,566 @@
+//
+// 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 <d3dx9.h>
+
+#include "common/debug.h"
+
+#include "libGLESv2/main.h"
+
+namespace
+{
+// 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.
+const char standardvs[] =
+"struct VS_OUTPUT\n"
+"{\n"
+" float4 position : POSITION;\n"
+" float4 texcoord : TEXCOORD0;\n"
+"};\n"
+"\n"
+"uniform float4 halfPixelSize : c0;\n"
+"\n"
+"VS_OUTPUT main(in float4 position : POSITION)\n"
+"{\n"
+" VS_OUTPUT Out;\n"
+"\n"
+" Out.position = position + halfPixelSize;\n"
+" Out.texcoord = position * float4(0.5, -0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0);\n"
+"\n"
+" return Out;\n"
+"}\n";
+
+// 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.
+const char flipyvs[] =
+"struct VS_OUTPUT\n"
+"{\n"
+" float4 position : POSITION;\n"
+" float4 texcoord : TEXCOORD0;\n"
+"};\n"
+"\n"
+"uniform float4 halfPixelSize : c0;\n"
+"\n"
+"VS_OUTPUT main(in float4 position : POSITION)\n"
+"{\n"
+" VS_OUTPUT Out;\n"
+"\n"
+" Out.position = position + halfPixelSize;\n"
+" Out.texcoord = position * float4(0.5, 0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0);\n"
+"\n"
+" return Out;\n"
+"}\n";
+
+// Passthrough Pixel Shader
+// Outputs texture 0 sampled at texcoord 0.
+const char passthroughps[] =
+"sampler2D tex : s0;\n"
+"\n"
+"float4 main(float4 texcoord : TEXCOORD0) : COLOR\n"
+"{\n"
+" return tex2D(tex, texcoord.xy);\n"
+"}\n";
+
+// 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.
+const char luminanceps[] =
+"sampler2D tex : s0;\n"
+"\n"
+"uniform float4 mode : c0;\n"
+"\n"
+"float4 main(float4 texcoord : TEXCOORD0) : COLOR\n"
+"{\n"
+" float4 tmp = tex2D(tex, texcoord.xy);\n"
+" tmp.w = tmp.w * mode.x + mode.y;\n"
+" return tmp.xxxw;\n"
+"}\n";
+
+// 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.
+const char componentmaskps[] =
+"sampler2D tex : s0;\n"
+"\n"
+"uniform float4 mode : c0;\n"
+"\n"
+"float4 main(float4 texcoord : TEXCOORD0) : COLOR\n"
+"{\n"
+" float4 tmp = tex2D(tex, texcoord.xy);\n"
+" tmp.xyz = tmp.xyz * mode.x;\n"
+" tmp.w = tmp.w * mode.z + mode.w;\n"
+" return tmp;\n"
+"}\n";
+
+}
+
+namespace gl
+{
+
+const char * const Blit::mShaderSource[] =
+{
+ standardvs,
+ flipyvs,
+ passthroughps,
+ luminanceps,
+ componentmaskps
+};
+
+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 hr = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL);
+
+ if (FAILED(hr))
+ {
+ ASSERT(hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+ return error(GL_OUT_OF_MEMORY);
+ }
+
+ void *lockPtr;
+ mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
+ memcpy(lockPtr, quad, sizeof(quad));
+ mQuadVertexBuffer->Unlock();
+
+ static const D3DVERTEXELEMENT9 elements[] =
+ {
+ { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
+ D3DDECL_END()
+ };
+
+ hr = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
+ if (FAILED(hr))
+ {
+ ASSERT(hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+template <class D3DShaderType>
+bool Blit::setShader(ShaderId source, const char *profile,
+ HRESULT (WINAPI IDirect3DDevice9::*createShader)(const DWORD *, D3DShaderType**),
+ HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
+{
+ IDirect3DDevice9 *device = getDevice();
+
+ D3DShaderType *shader;
+
+ if (mCompiledShaders[source] != NULL)
+ {
+ shader = static_cast<D3DShaderType*>(mCompiledShaders[source]);
+ }
+ else
+ {
+ ID3DXBuffer *shaderCode;
+ HRESULT hr = D3DXCompileShader(mShaderSource[source], strlen(mShaderSource[source]), NULL, NULL, "main", profile, 0, &shaderCode, NULL, NULL);
+
+ if (FAILED(hr))
+ {
+ ERR("Failed to compile %s shader for blit operation %d, error 0x%08X.", profile, (int)source, hr);
+ return false;
+ }
+
+ hr = (device->*createShader)(static_cast<const DWORD*>(shaderCode->GetBufferPointer()), &shader);
+ if (FAILED(hr))
+ {
+ shaderCode->Release();
+ ERR("Failed to create %s shader for blit operation %d, error 0x%08X.", profile, (int)source, hr);
+ return false;
+ }
+
+ shaderCode->Release();
+
+ mCompiledShaders[source] = shader;
+ }
+
+ HRESULT hr = (device->*setShader)(shader);
+
+ if (FAILED(hr))
+ {
+ ERR("Failed to set %s shader for blit operation %d, error 0x%08X.", profile, (int)source, hr);
+ return false;
+ }
+
+ return true;
+}
+
+bool Blit::setVertexShader(ShaderId shader)
+{
+ return setShader<IDirect3DVertexShader9>(shader, mContext->supportsShaderModel3() ? "vs_3_0" : "vs_2_0", &IDirect3DDevice9::CreateVertexShader, &IDirect3DDevice9::SetVertexShader);
+}
+
+bool Blit::setPixelShader(ShaderId shader)
+{
+ return setShader<IDirect3DPixelShader9>(shader, mContext->supportsShaderModel3() ? "ps_3_0" : "ps_2_0", &IDirect3DDevice9::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::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)
+{
+ 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);
+ }
+
+ RECT d3dSourceRect;
+ d3dSourceRect.left = sourceRect.left;
+ d3dSourceRect.right = sourceRect.right;
+ d3dSourceRect.top = sourceRect.top;
+ d3dSourceRect.bottom = sourceRect.bottom;
+
+ display->endScene();
+ result = device->StretchRect(surface, &d3dSourceRect, 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);
+
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS+1; 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/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.h
new file mode 100644
index 0000000..a83aac3
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.h
@@ -0,0 +1,90 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// 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"
+
+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)
+ // 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
+ };
+
+ static const char * const mShaderSource[];
+
+ // This actually contains IDirect3DVertexShader9 or IDirect3DPixelShader9 casted to IUnknown.
+ IUnknown *mCompiledShaders[SHADER_COUNT];
+
+ template <class D3DShaderType>
+ bool setShader(ShaderId source, const char *profile,
+ HRESULT (WINAPI IDirect3DDevice9::*createShader)(const DWORD *, D3DShaderType **),
+ 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/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.cpp
new file mode 100644
index 0000000..43993e7
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.cpp
@@ -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.
+//
+
+// 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"
+
+namespace gl
+{
+
+Buffer::Buffer(GLuint id) : RefCountObject(id)
+{
+ mContents = NULL;
+ mSize = 0;
+ mUsage = GL_DYNAMIC_DRAW;
+}
+
+Buffer::~Buffer()
+{
+ delete[] mContents;
+}
+
+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;
+}
+
+void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
+{
+ memcpy(mContents + offset, data, size);
+}
+
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.h
new file mode 100644
index 0000000..5611cc9
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.h
@@ -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.
+//
+
+// 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 "libGLESv2/RefCountObject.h"
+
+namespace gl
+{
+
+class Buffer : public RefCountObject
+{
+ public:
+ explicit Buffer(GLuint id);
+
+ virtual ~Buffer();
+
+ void bufferData(const void *data, GLsizeiptr size, GLenum usage);
+ void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset);
+
+ void *data() { return mContents; }
+ size_t size() const { return mSize; }
+ GLenum usage() const { return mUsage; }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Buffer);
+
+ GLubyte *mContents;
+ size_t mSize;
+ GLenum mUsage;
+};
+
+}
+
+#endif // LIBGLESV2_BUFFER_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp
new file mode 100644
index 0000000..48ef8fc
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp
@@ -0,0 +1,3319 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Context.cpp: Implements the gl::Context class, managing all GL state and performing
+// rendering operations. It is the GLES2 specific implementation of EGLContext.
+
+#include "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/FrameBuffer.h"
+#include "libGLESv2/Program.h"
+#include "libGLESv2/RenderBuffer.h"
+#include "libGLESv2/Shader.h"
+#include "libGLESv2/Texture.h"
+#include "libGLESv2/geometry/backend.h"
+#include "libGLESv2/geometry/VertexDataManager.h"
+#include "libGLESv2/geometry/IndexDataManager.h"
+#include "libGLESv2/geometry/dx9.h"
+
+#undef near
+#undef far
+
+namespace gl
+{
+Context::Context(const egl::Config *config, const gl::Context *shareContext)
+ : mConfig(config)
+{
+ 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.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 = new Texture2D(0);
+ mTextureCubeMapZero = new TextureCubeMap(0);
+
+ mColorbufferZero = NULL;
+ mDepthStencilbufferZero = NULL;
+
+ mState.activeSampler = 0;
+ bindArrayBuffer(0);
+ bindElementArrayBuffer(0);
+ bindTextureCubeMap(0);
+ bindTexture2D(0);
+ bindReadFramebuffer(0);
+ bindDrawFramebuffer(0);
+ bindRenderbuffer(0);
+
+ for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
+ {
+ mIncompleteTextures[type] = NULL;
+ }
+
+ mState.currentProgram = 0;
+
+ mState.packAlignment = 4;
+ mState.unpackAlignment = 4;
+
+ mBufferBackEnd = NULL;
+ mVertexDataManager = NULL;
+ mIndexDataManager = NULL;
+ mBlit = NULL;
+
+ mInvalidEnum = false;
+ mInvalidValue = false;
+ mInvalidOperation = false;
+ mOutOfMemory = false;
+ mInvalidFramebufferOperation = false;
+
+ mHasBeenCurrent = false;
+
+ mMaxSupportedSamples = 0;
+ mMaskedClearSavedState = NULL;
+ markAllStateDirty();
+}
+
+Context::~Context()
+{
+ if (mState.currentProgram != 0)
+ {
+ Program *programObject = mResourceManager->getProgram(mState.currentProgram);
+ if (programObject)
+ {
+ programObject->release();
+ }
+ mState.currentProgram = 0;
+ }
+
+ while (!mFramebufferMap.empty())
+ {
+ deleteFramebuffer(mFramebufferMap.begin()->first);
+ }
+
+ while (!mMultiSampleSupport.empty())
+ {
+ delete [] mMultiSampleSupport.begin()->second;
+ mMultiSampleSupport.erase(mMultiSampleSupport.begin());
+ }
+
+ for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
+ {
+ for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
+ {
+ mState.samplerTexture[type][sampler].set(NULL);
+ }
+ }
+
+ for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
+ {
+ delete mIncompleteTextures[type];
+ }
+
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ mState.vertexAttribute[i].mBoundBuffer.set(NULL);
+ }
+
+ mState.arrayBuffer.set(NULL);
+ mState.elementArrayBuffer.set(NULL);
+ mState.texture2D.set(NULL);
+ mState.textureCubeMap.set(NULL);
+ mState.renderbuffer.set(NULL);
+
+ delete mTexture2DZero;
+ delete mTextureCubeMapZero;
+
+ delete mBufferBackEnd;
+ delete mVertexDataManager;
+ delete mIndexDataManager;
+ delete mBlit;
+
+ if (mMaskedClearSavedState)
+ {
+ mMaskedClearSavedState->Release();
+ }
+
+ mResourceManager->release();
+}
+
+void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
+{
+ IDirect3DDevice9 *device = display->getDevice();
+
+ if (!mHasBeenCurrent)
+ {
+ mDeviceCaps = display->getDeviceCaps();
+
+ mBufferBackEnd = new Dx9BackEnd(this, device);
+ mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
+ mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
+ mBlit = new Blit(this);
+
+ 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];
+ display->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;
+
+ mSupportsCompressedTextures = display->getCompressedTextureSupport();
+
+ initExtensionString();
+
+ mState.viewportX = 0;
+ mState.viewportY = 0;
+ mState.viewportWidth = surface->getWidth();
+ mState.viewportHeight = surface->getHeight();
+
+ mState.scissorX = 0;
+ mState.scissorY = 0;
+ mState.scissorWidth = surface->getWidth();
+ mState.scissorHeight = surface->getHeight();
+
+ mHasBeenCurrent = true;
+ }
+
+ // Wrap the existing 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);
+
+ defaultRenderTarget->Release();
+
+ if (depthStencil)
+ {
+ depthStencil->Release();
+ }
+
+ mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0);
+
+ 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()
+{
+ mAppliedRenderTargetSerial = 0;
+ mAppliedDepthbufferSerial = 0;
+ mAppliedProgram = 0;
+
+ mClearStateDirty = true;
+ mCullStateDirty = true;
+ mDepthStateDirty = true;
+ mMaskStateDirty = true;
+ mBlendStateDirty = true;
+ mStencilStateDirty = true;
+ mPolygonOffsetStateDirty = true;
+ mScissorStateDirty = true;
+ mSampleStateDirty = true;
+ mDitherStateDirty = true;
+ mFrontFaceDirty = true;
+
+ if (mBufferBackEnd != NULL)
+ {
+ mBufferBackEnd->invalidate();
+ }
+}
+
+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::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(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();
+}
+
+void Context::setVertexAttribEnabled(unsigned int attribNum, bool enabled)
+{
+ mState.vertexAttribute[attribNum].mEnabled = enabled;
+}
+
+const AttributeState &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;
+}
+
+// returns entire set of attributes as a block
+const AttributeState *Context::getVertexAttribBlock()
+{
+ return mState.vertexAttribute;
+}
+
+void Context::setPackAlignment(GLint alignment)
+{
+ mState.packAlignment = alignment;
+}
+
+GLint Context::getPackAlignment() const
+{
+ return mState.packAlignment;
+}
+
+void Context::setUnpackAlignment(GLint alignment)
+{
+ mState.unpackAlignment = alignment;
+}
+
+GLint Context::getUnpackAlignment() const
+{
+ return mState.unpackAlignment;
+}
+
+GLuint Context::createBuffer()
+{
+ return mResourceManager->createBuffer();
+}
+
+GLuint Context::createProgram()
+{
+ return mResourceManager->createProgram();
+}
+
+GLuint Context::createShader(GLenum type)
+{
+ return mResourceManager->createShader(type);
+}
+
+GLuint Context::createTexture()
+{
+ return mResourceManager->createTexture();
+}
+
+GLuint Context::createRenderbuffer()
+{
+ return mResourceManager->createRenderbuffer();
+}
+
+// Returns an unused framebuffer name
+GLuint Context::createFramebuffer()
+{
+ unsigned int handle = 1;
+
+ while (mFramebufferMap.find(handle) != mFramebufferMap.end())
+ {
+ handle++;
+ }
+
+ mFramebufferMap[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);
+
+ delete framebufferObject->second;
+ mFramebufferMap.erase(framebufferObject);
+ }
+}
+
+Buffer *Context::getBuffer(GLuint handle)
+{
+ return mResourceManager->getBuffer(handle);
+}
+
+Shader *Context::getShader(GLuint handle)
+{
+ return mResourceManager->getShader(handle);
+}
+
+Program *Context::getProgram(GLuint handle)
+{
+ return mResourceManager->getProgram(handle);
+}
+
+Texture *Context::getTexture(GLuint handle)
+{
+ return mResourceManager->getTexture(handle);
+}
+
+Renderbuffer *Context::getRenderbuffer(GLuint handle)
+{
+ return mResourceManager->getRenderbuffer(handle);
+}
+
+Framebuffer *Context::getReadFramebuffer()
+{
+ return getFramebuffer(mState.readFramebuffer);
+}
+
+Framebuffer *Context::getDrawFramebuffer()
+{
+ return getFramebuffer(mState.drawFramebuffer);
+}
+
+void Context::bindArrayBuffer(unsigned int buffer)
+{
+ mResourceManager->checkBufferAllocation(buffer);
+
+ mState.arrayBuffer.set(getBuffer(buffer));
+}
+
+void Context::bindElementArrayBuffer(unsigned int buffer)
+{
+ mResourceManager->checkBufferAllocation(buffer);
+
+ mState.elementArrayBuffer.set(getBuffer(buffer));
+}
+
+void Context::bindTexture2D(GLuint texture)
+{
+ mResourceManager->checkTextureAllocation(texture, SAMPLER_2D);
+
+ mState.texture2D.set(getTexture(texture));
+
+ mState.samplerTexture[SAMPLER_2D][mState.activeSampler].set(mState.texture2D.get());
+}
+
+void Context::bindTextureCubeMap(GLuint texture)
+{
+ mResourceManager->checkTextureAllocation(texture, SAMPLER_CUBE);
+
+ mState.textureCubeMap.set(getTexture(texture));
+
+ mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].set(mState.textureCubeMap.get());
+}
+
+void Context::bindReadFramebuffer(GLuint framebuffer)
+{
+ if (!getFramebuffer(framebuffer))
+ {
+ mFramebufferMap[framebuffer] = new Framebuffer();
+ }
+
+ mState.readFramebuffer = framebuffer;
+}
+
+void Context::bindDrawFramebuffer(GLuint framebuffer)
+{
+ if (!getFramebuffer(framebuffer))
+ {
+ mFramebufferMap[framebuffer] = new Framebuffer();
+ }
+
+ mState.drawFramebuffer = framebuffer;
+}
+
+void Context::bindRenderbuffer(GLuint renderbuffer)
+{
+ mResourceManager->checkRenderbufferAllocation(renderbuffer);
+
+ mState.renderbuffer.set(getRenderbuffer(renderbuffer));
+}
+
+void Context::useProgram(GLuint program)
+{
+ GLuint priorProgram = mState.currentProgram;
+ mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
+
+ if (priorProgram != program)
+ {
+ Program *newProgram = mResourceManager->getProgram(program);
+ Program *oldProgram = mResourceManager->getProgram(priorProgram);
+
+ if (newProgram)
+ {
+ newProgram->addRef();
+ }
+
+ if (oldProgram)
+ {
+ oldProgram->release();
+ }
+ }
+}
+
+void Context::setFramebufferZero(Framebuffer *buffer)
+{
+ delete mFramebufferMap[0];
+ mFramebufferMap[0] = buffer;
+}
+
+void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer)
+{
+ Renderbuffer *renderbufferObject = mState.renderbuffer.get();
+ renderbufferObject->setStorage(renderbuffer);
+}
+
+Framebuffer *Context::getFramebuffer(unsigned int handle)
+{
+ FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
+
+ if (framebuffer == mFramebufferMap.end())
+ {
+ return NULL;
+ }
+ else
+ {
+ return framebuffer->second;
+ }
+}
+
+Buffer *Context::getArrayBuffer()
+{
+ return mState.arrayBuffer.get();
+}
+
+Buffer *Context::getElementArrayBuffer()
+{
+ return mState.elementArrayBuffer.get();
+}
+
+Program *Context::getCurrentProgram()
+{
+ return mResourceManager->getProgram(mState.currentProgram);
+}
+
+Texture2D *Context::getTexture2D()
+{
+ if (mState.texture2D.id() == 0) // Special case: 0 refers to different initial textures based on the target
+ {
+ return mTexture2DZero;
+ }
+
+ return static_cast<Texture2D*>(mState.texture2D.get());
+}
+
+TextureCubeMap *Context::getTextureCubeMap()
+{
+ if (mState.textureCubeMap.id() == 0) // Special case: 0 refers to different initial textures based on the target
+ {
+ return mTextureCubeMapZero;
+ }
+
+ return static_cast<TextureCubeMap*>(mState.textureCubeMap.get());
+}
+
+Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
+{
+ GLuint texid = mState.samplerTexture[type][sampler].id();
+
+ if (texid == 0)
+ {
+ switch (type)
+ {
+ default: UNREACHABLE();
+ case SAMPLER_2D: return mTexture2DZero;
+ case SAMPLER_CUBE: return mTextureCubeMapZero;
+ }
+ }
+
+ 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;
+ case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage;
+ case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage;
+ case GL_SCISSOR_TEST: *params = mState.scissorTest;
+ case GL_STENCIL_TEST: *params = mState.stencilTest;
+ case GL_DEPTH_TEST: *params = mState.depthTest;
+ case GL_BLEND: *params = mState.blend;
+ case GL_DITHER: *params = mState.dither;
+ 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] = supportsShaderModel3() ? gl::ALIASED_POINT_SIZE_RANGE_MAX_SM3 : gl::ALIASED_POINT_SIZE_RANGE_MAX_SM2;
+ 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;
+ 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 = gl::MAX_VARYING_VECTORS; break;
+ case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
+ case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
+ case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
+ case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break;
+ case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break;
+ case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
+ case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
+ case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.id(); break;
+ case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer.id(); break;
+ //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
+ case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mState.drawFramebuffer; break;
+ case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mState.readFramebuffer; break;
+ case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.id(); break;
+ case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
+ case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
+ case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
+ case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
+ case GL_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 = gl::MAX_TEXTURE_SIZE; break;
+ case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; break;
+ case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
+ {
+ if (supportsCompressedTextures())
+ {
+ // at current, only GL_COMPRESSED_RGB_S3TC_DXT1_EXT and
+ // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT are supported
+ *params = 2;
+ }
+ else
+ {
+ *params = 0;
+ }
+ }
+ 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: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break;
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
+ case GL_MAX_VIEWPORT_DIMS:
+ {
+ int maxDimension = std::max((int)gl::MAX_RENDERBUFFER_SIZE, (int)gl::MAX_TEXTURE_SIZE);
+ params[0] = maxDimension;
+ params[1] = maxDimension;
+ }
+ break;
+ case GL_COMPRESSED_TEXTURE_FORMATS:
+ {
+ if (supportsCompressedTextures())
+ {
+ params[0] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ params[1] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ }
+ }
+ 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::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
+
+ if (colorbuffer)
+ {
+ switch (pname)
+ {
+ case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
+ case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
+ case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
+ case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
+ }
+ }
+ else
+ {
+ *params = 0;
+ }
+ }
+ break;
+ case GL_DEPTH_BITS:
+ {
+ gl::Framebuffer *framebuffer = getDrawFramebuffer();
+ gl::DepthStencilbuffer *depthbuffer = framebuffer->getDepthbuffer();
+
+ if (depthbuffer)
+ {
+ *params = depthbuffer->getDepthSize();
+ }
+ else
+ {
+ *params = 0;
+ }
+ }
+ break;
+ case GL_STENCIL_BITS:
+ {
+ gl::Framebuffer *framebuffer = getDrawFramebuffer();
+ gl::DepthStencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
+
+ if (stencilbuffer)
+ {
+ *params = stencilbuffer->getStencilSize();
+ }
+ else
+ {
+ *params = 0;
+ }
+ }
+ break;
+ case GL_TEXTURE_BINDING_2D:
+ {
+ if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
+ {
+ error(GL_INVALID_OPERATION);
+ return false;
+ }
+
+ *params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler].id();
+ }
+ break;
+ case GL_TEXTURE_BINDING_CUBE_MAP:
+ {
+ if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
+ {
+ error(GL_INVALID_OPERATION);
+ return false;
+ }
+
+ *params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].id();
+ }
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
+{
+ // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
+ // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
+ // to the fact that it is stored internally as a float, and so would require conversion
+ // if returned from Context::getIntegerv. Since this conversion is already implemented
+ // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
+ // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
+ // application.
+ switch (pname)
+ {
+ case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
+ case GL_SHADER_BINARY_FORMATS:
+ {
+ *type = GL_INT;
+ *numParams = 0;
+ }
+ break;
+ case GL_MAX_VERTEX_ATTRIBS:
+ case GL_MAX_VERTEX_UNIFORM_VECTORS:
+ case GL_MAX_VARYING_VECTORS:
+ case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
+ case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
+ case GL_MAX_TEXTURE_IMAGE_UNITS:
+ case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
+ case GL_MAX_RENDERBUFFER_SIZE:
+ case GL_NUM_SHADER_BINARY_FORMATS:
+ case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
+ case GL_ARRAY_BUFFER_BINDING:
+ case GL_FRAMEBUFFER_BINDING:
+ case GL_RENDERBUFFER_BINDING:
+ case GL_CURRENT_PROGRAM:
+ case GL_PACK_ALIGNMENT:
+ case GL_UNPACK_ALIGNMENT:
+ case GL_GENERATE_MIPMAP_HINT:
+ case GL_RED_BITS:
+ case GL_GREEN_BITS:
+ case GL_BLUE_BITS:
+ case GL_ALPHA_BITS:
+ case GL_DEPTH_BITS:
+ case GL_STENCIL_BITS:
+ case GL_ELEMENT_ARRAY_BUFFER_BINDING:
+ case GL_CULL_FACE_MODE:
+ case GL_FRONT_FACE:
+ case GL_ACTIVE_TEXTURE:
+ case GL_STENCIL_FUNC:
+ case GL_STENCIL_VALUE_MASK:
+ case GL_STENCIL_REF:
+ case GL_STENCIL_FAIL:
+ case GL_STENCIL_PASS_DEPTH_FAIL:
+ case GL_STENCIL_PASS_DEPTH_PASS:
+ case GL_STENCIL_BACK_FUNC:
+ case GL_STENCIL_BACK_VALUE_MASK:
+ case GL_STENCIL_BACK_REF:
+ case GL_STENCIL_BACK_FAIL:
+ case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
+ case GL_STENCIL_BACK_PASS_DEPTH_PASS:
+ case GL_DEPTH_FUNC:
+ case GL_BLEND_SRC_RGB:
+ case GL_BLEND_SRC_ALPHA:
+ case GL_BLEND_DST_RGB:
+ case GL_BLEND_DST_ALPHA:
+ case GL_BLEND_EQUATION_RGB:
+ case GL_BLEND_EQUATION_ALPHA:
+ case GL_STENCIL_WRITEMASK:
+ case GL_STENCIL_BACK_WRITEMASK:
+ case GL_STENCIL_CLEAR_VALUE:
+ case GL_SUBPIXEL_BITS:
+ case GL_MAX_TEXTURE_SIZE:
+ case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
+ case GL_SAMPLE_BUFFERS:
+ case GL_SAMPLES:
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+ case GL_TEXTURE_BINDING_2D:
+ case GL_TEXTURE_BINDING_CUBE_MAP:
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ }
+ break;
+ case GL_MAX_SAMPLES_ANGLE:
+ {
+ 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:
+ {
+ *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;
+ 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)
+{
+ IDirect3DDevice9 *device = getDevice();
+
+ Framebuffer *framebufferObject = getDrawFramebuffer();
+
+ if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
+ {
+ error(GL_INVALID_FRAMEBUFFER_OPERATION);
+
+ return false;
+ }
+
+ IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
+ IDirect3DSurface9 *depthStencil = NULL;
+
+ unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial();
+ if (renderTargetSerial != mAppliedRenderTargetSerial)
+ {
+ device->SetRenderTarget(0, renderTarget);
+ mAppliedRenderTargetSerial = renderTargetSerial;
+ mScissorStateDirty = true; // Scissor area must be clamped to render target's size-- this is different for different render targets.
+ }
+
+ unsigned int depthbufferSerial = 0;
+ unsigned int stencilbufferSerial = 0;
+ if (framebufferObject->getDepthbufferType() != GL_NONE)
+ {
+ depthStencil = framebufferObject->getDepthbuffer()->getDepthStencil();
+ depthbufferSerial = framebufferObject->getDepthbuffer()->getSerial();
+ }
+ else if (framebufferObject->getStencilbufferType() != GL_NONE)
+ {
+ depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
+ stencilbufferSerial = framebufferObject->getStencilbuffer()->getSerial();
+ }
+
+ if (depthbufferSerial != mAppliedDepthbufferSerial ||
+ stencilbufferSerial != mAppliedStencilbufferSerial)
+ {
+ device->SetDepthStencilSurface(depthStencil);
+ mAppliedDepthbufferSerial = depthbufferSerial;
+ mAppliedStencilbufferSerial = stencilbufferSerial;
+ }
+
+ D3DVIEWPORT9 viewport;
+ D3DSURFACE_DESC desc;
+ renderTarget->GetDesc(&desc);
+
+ if (ignoreViewport)
+ {
+ viewport.X = 0;
+ viewport.Y = 0;
+ viewport.Width = desc.Width;
+ viewport.Height = desc.Height;
+ viewport.MinZ = 0.0f;
+ viewport.MaxZ = 1.0f;
+ }
+ else
+ {
+ viewport.X = std::max(mState.viewportX, 0);
+ viewport.Y = std::max(mState.viewportY, 0);
+ viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
+ viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
+ viewport.MinZ = clamp01(mState.zNear);
+ viewport.MaxZ = clamp01(mState.zFar);
+ }
+
+ if (viewport.Width <= 0 || viewport.Height <= 0)
+ {
+ return false; // Nothing to render
+ }
+
+ device->SetViewport(&viewport);
+
+ if (mScissorStateDirty)
+ {
+ if (mState.scissorTest)
+ {
+ RECT rect = {mState.scissorX,
+ mState.scissorY,
+ mState.scissorX + mState.scissorWidth,
+ mState.scissorY + mState.scissorHeight};
+ rect.right = std::min(static_cast<UINT>(rect.right), desc.Width);
+ rect.bottom = std::min(static_cast<UINT>(rect.bottom), desc.Height);
+ device->SetScissorRect(&rect);
+ device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
+ }
+ else
+ {
+ device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
+ }
+
+ mScissorStateDirty = false;
+ }
+
+ if (mState.currentProgram)
+ {
+ Program *programObject = getCurrentProgram();
+
+ GLint halfPixelSize = programObject->getDxHalfPixelSizeLocation();
+ GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
+ programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
+
+ GLint window = programObject->getDxViewportLocation();
+ 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};
+ programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
+
+ GLint depth = programObject->getDxDepthLocation();
+ GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f};
+ programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
+
+ GLint near = programObject->getDepthRangeNearLocation();
+ programObject->setUniform1fv(near, 1, &mState.zNear);
+
+ GLint far = programObject->getDepthRangeFarLocation();
+ programObject->setUniform1fv(far, 1, &mState.zFar);
+
+ GLint diff = programObject->getDepthRangeDiffLocation();
+ GLfloat zDiff = mState.zFar - mState.zNear;
+ programObject->setUniform1fv(diff, 1, &zDiff);
+ }
+
+ return true;
+}
+
+// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
+void Context::applyState(GLenum drawMode)
+{
+ IDirect3DDevice9 *device = getDevice();
+ Program *programObject = getCurrentProgram();
+
+ GLint frontCCW = programObject->getDxFrontCCWLocation();
+ GLint ccw = (mState.frontFace == GL_CCW);
+ programObject->setUniform1iv(frontCCW, 1, &ccw);
+
+ GLint pointsOrLines = programObject->getDxPointsOrLinesLocation();
+ GLint alwaysFront = !isTriangleMode(drawMode);
+ programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
+
+ Framebuffer *framebufferObject = getDrawFramebuffer();
+
+ if (mCullStateDirty || mFrontFaceDirty)
+ {
+ if (mState.cullFace)
+ {
+ device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
+ }
+ else
+ {
+ device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ }
+
+ mCullStateDirty = false;
+ }
+
+ if (mDepthStateDirty)
+ {
+ if (mState.depthTest && framebufferObject->getDepthbufferType() != GL_NONE)
+ {
+ device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
+ device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
+ }
+ else
+ {
+ device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
+ }
+
+ mDepthStateDirty = false;
+ }
+
+ if (mBlendStateDirty)
+ {
+ if (mState.blend)
+ {
+ device->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)
+ {
+ device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
+ }
+ else
+ {
+ device->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)));
+ }
+
+ device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
+ device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
+ device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
+
+ if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
+ mState.destBlendRGB != mState.destBlendAlpha ||
+ mState.blendEquationRGB != mState.blendEquationAlpha)
+ {
+ device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+
+ device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
+ device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
+ device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
+
+ }
+ else
+ {
+ device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
+ }
+ }
+ else
+ {
+ device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ }
+
+ mBlendStateDirty = false;
+ }
+
+ if (mStencilStateDirty || mFrontFaceDirty)
+ {
+ if (mState.stencilTest && framebufferObject->hasStencil())
+ {
+ device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+ device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
+
+ // FIXME: Unsupported by D3D9
+ const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
+ const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
+ const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
+ 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::DepthStencilbuffer *stencilbuffer = framebufferObject->getStencilbuffer();
+ GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
+
+ device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
+ device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
+ es2dx::ConvertComparison(mState.stencilFunc));
+
+ device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
+ device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
+
+ device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
+ es2dx::ConvertStencilOp(mState.stencilFail));
+ device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
+ es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
+ device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
+ es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
+
+ device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
+ device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
+ es2dx::ConvertComparison(mState.stencilBackFunc));
+
+ device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
+ device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
+
+ device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
+ es2dx::ConvertStencilOp(mState.stencilBackFail));
+ device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
+ es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
+ device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
+ es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
+ }
+ else
+ {
+ device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ }
+
+ mStencilStateDirty = false;
+ }
+
+ if (mMaskStateDirty)
+ {
+ device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
+ mState.colorMaskBlue, mState.colorMaskAlpha));
+ device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
+
+ mMaskStateDirty = false;
+ }
+
+ if (mPolygonOffsetStateDirty)
+ {
+ if (mState.polygonOffsetFill)
+ {
+ gl::DepthStencilbuffer *depthbuffer = framebufferObject->getDepthbuffer();
+ if (depthbuffer)
+ {
+ device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
+ float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
+ device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
+ }
+ }
+ else
+ {
+ device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
+ device->SetRenderState(D3DRS_DEPTHBIAS, 0);
+ }
+
+ mPolygonOffsetStateDirty = false;
+ }
+
+ if (framebufferObject->isMultisample() && mSampleStateDirty)
+ {
+ if (mState.sampleAlphaToCoverage)
+ {
+ FIXME("Sample alpha to coverage is unimplemented.");
+ }
+
+ if (mState.sampleCoverage)
+ {
+ device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
+ 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;
+ }
+
+ device->SetRenderState(D3DRS_MULTISAMPLEMASK, mask);
+ }
+ else
+ {
+ device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE);
+ }
+
+ mSampleStateDirty = false;
+ }
+
+ if (mDitherStateDirty)
+ {
+ device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
+
+ mDitherStateDirty = false;
+ }
+
+ mFrontFaceDirty = false;
+}
+
+// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
+void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
+{
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (attributes[i].enabled)
+ {
+ attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
+ }
+ }
+}
+
+GLenum Context::applyVertexBuffer(GLenum mode, GLint first, GLsizei count, bool *useIndexing, TranslatedIndexData *indexInfo)
+{
+ TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
+
+ GLenum err = mVertexDataManager->preRenderValidate(first, count, translated);
+ if (err != GL_NO_ERROR)
+ {
+ return err;
+ }
+
+ lookupAttributeMapping(translated);
+
+ mBufferBackEnd->setupAttributesPreDraw(translated);
+
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (translated[i].enabled && translated[i].nonArray)
+ {
+ err = mIndexDataManager->preRenderValidateUnindexed(mode, count, indexInfo);
+ if (err != GL_NO_ERROR)
+ {
+ return err;
+ }
+
+ mBufferBackEnd->setupIndicesPreDraw(*indexInfo);
+
+ *useIndexing = true;
+ return GL_NO_ERROR;
+ }
+ }
+
+ *useIndexing = false;
+ return GL_NO_ERROR;
+}
+
+GLenum Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
+{
+ TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
+
+ GLenum err = mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
+
+ if (err == GL_NO_ERROR)
+ {
+ lookupAttributeMapping(translated);
+
+ mBufferBackEnd->setupAttributesPreDraw(translated);
+ }
+
+ return err;
+}
+
+// Applies the indices and element array bindings to the Direct3D 9 device
+GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
+{
+ GLenum err = mIndexDataManager->preRenderValidate(mode, type, count, mState.elementArrayBuffer.get(), indices, indexInfo);
+
+ if (err == GL_NO_ERROR)
+ {
+ mBufferBackEnd->setupIndicesPreDraw(*indexInfo);
+ }
+
+ return err;
+}
+
+// Applies the shaders and shader constants to the Direct3D 9 device
+void Context::applyShaders()
+{
+ IDirect3DDevice9 *device = getDevice();
+ Program *programObject = getCurrentProgram();
+ IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
+ IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
+
+ device->SetVertexShader(vertexShader);
+ device->SetPixelShader(pixelShader);
+
+ if (programObject->getSerial() != mAppliedProgram)
+ {
+ programObject->dirtyAllUniforms();
+ programObject->dirtyAllSamplers();
+ mAppliedProgram = programObject->getSerial();
+ }
+
+ programObject->applyUniforms();
+}
+
+// Applies the textures and sampler states to the Direct3D 9 device
+void Context::applyTextures()
+{
+ IDirect3DDevice9 *device = getDevice();
+ Program *programObject = getCurrentProgram();
+
+ for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
+ {
+ int textureUnit = programObject->getSamplerMapping(sampler);
+ if (textureUnit != -1)
+ {
+ SamplerType textureType = programObject->getSamplerType(sampler);
+
+ Texture *texture = getSamplerTexture(textureUnit, textureType);
+
+ if (programObject->isSamplerDirty(sampler) || texture->isDirty())
+ {
+ if (texture->isComplete())
+ {
+ GLenum wrapS = texture->getWrapS();
+ GLenum wrapT = texture->getWrapT();
+ GLenum minFilter = texture->getMinFilter();
+ GLenum magFilter = texture->getMagFilter();
+
+ device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
+ device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
+
+ device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
+ D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
+ es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
+ device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
+ device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
+
+ device->SetTexture(sampler, texture->getTexture());
+ }
+ else
+ {
+ device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
+ }
+ }
+
+ programObject->setSamplerDirty(sampler, false);
+ }
+ else
+ {
+ if (programObject->isSamplerDirty(sampler))
+ {
+ device->SetTexture(sampler, NULL);
+ programObject->setSamplerDirty(sampler, false);
+ }
+ }
+ }
+}
+
+void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, 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);
+ }
+
+ IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
+ IDirect3DDevice9 *device = getDevice();
+
+ D3DSURFACE_DESC desc;
+ renderTarget->GetDesc(&desc);
+
+ IDirect3DSurface9 *systemSurface;
+ HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
+
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+
+ ASSERT(SUCCEEDED(result));
+
+ if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
+ {
+ UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
+ }
+
+ result = device->GetRenderTargetData(renderTarget, systemSurface);
+
+ if (FAILED(result))
+ {
+ systemSurface->Release();
+
+ switch (result)
+ {
+ case D3DERR_DRIVERINTERNALERROR:
+ case D3DERR_DEVICELOST:
+ return error(GL_OUT_OF_MEMORY);
+ default:
+ UNREACHABLE();
+ return; // No sensible error to generate
+ }
+ }
+
+ D3DLOCKED_RECT lock;
+ RECT rect = {std::max(x, 0),
+ std::max(y, 0),
+ std::min(x + width, (int)desc.Width),
+ std::min(y + height, (int)desc.Height)};
+
+ result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
+
+ if (FAILED(result))
+ {
+ UNREACHABLE();
+ systemSurface->Release();
+
+ return; // No sensible error to generate
+ }
+
+ unsigned char *source = (unsigned char*)lock.pBits;
+ unsigned char *dest = (unsigned char*)pixels;
+ unsigned short *dest16 = (unsigned short*)pixels;
+
+ GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
+
+ for (int j = 0; j < rect.bottom - rect.top; j++)
+ {
+ if (desc.Format == D3DFMT_A8R8G8B8 &&
+ format == GL_BGRA_EXT &&
+ type == GL_UNSIGNED_BYTE)
+ {
+ // Fast path for EXT_read_format_bgra, given
+ // an RGBA source buffer. Note that buffers with no
+ // alpha go through the slow path below.
+ memcpy(dest + j * outputPitch,
+ source + j * lock.Pitch,
+ (rect.right - rect.left) * 4);
+ 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 * lock.Pitch);
+
+ a = 1.0f;
+ b = (rgb & 0x001F) * (1.0f / 0x001F);
+ g = (rgb & 0x07E0) * (1.0f / 0x07E0);
+ r = (rgb & 0xF800) * (1.0f / 0xF800);
+ }
+ break;
+ case D3DFMT_X1R5G5B5:
+ {
+ unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
+
+ a = 1.0f;
+ b = (xrgb & 0x001F) * (1.0f / 0x001F);
+ g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
+ r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
+ }
+ break;
+ case D3DFMT_A1R5G5B5:
+ {
+ unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
+
+ a = (argb & 0x8000) ? 1.0f : 0.0f;
+ b = (argb & 0x001F) * (1.0f / 0x001F);
+ g = (argb & 0x03E0) * (1.0f / 0x03E0);
+ r = (argb & 0x7C00) * (1.0f / 0x7C00);
+ }
+ break;
+ case D3DFMT_A8R8G8B8:
+ {
+ unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
+
+ a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
+ b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
+ g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
+ r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
+ }
+ break;
+ case D3DFMT_X8R8G8B8:
+ {
+ unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
+
+ a = 1.0f;
+ b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
+ g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
+ r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
+ }
+ break;
+ case D3DFMT_A2R10G10B10:
+ {
+ unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
+
+ a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
+ b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
+ g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
+ r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
+ }
+ break;
+ default:
+ UNIMPLEMENTED(); // FIXME
+ UNREACHABLE();
+ }
+
+ switch (format)
+ {
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
+ dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
+ dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
+ dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
+ break;
+ default: UNREACHABLE();
+ }
+ break;
+ case GL_BGRA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f);
+ dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
+ dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f);
+ dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
+ // this type is packed as follows:
+ // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ // --------------------------------------------------------------------------------
+ // | 4th | 3rd | 2nd | 1st component |
+ // --------------------------------------------------------------------------------
+ // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
+ dest16[i + j * outputPitch / sizeof(unsigned short)] =
+ ((unsigned short)(15 * a + 0.5f) << 12)|
+ ((unsigned short)(15 * r + 0.5f) << 8) |
+ ((unsigned short)(15 * g + 0.5f) << 4) |
+ ((unsigned short)(15 * b + 0.5f) << 0);
+ break;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
+ // this type is packed as follows:
+ // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ // --------------------------------------------------------------------------------
+ // | 4th | 3rd | 2nd | 1st component |
+ // --------------------------------------------------------------------------------
+ // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
+ dest16[i + j * outputPitch / sizeof(unsigned short)] =
+ ((unsigned short)( a + 0.5f) << 15) |
+ ((unsigned short)(31 * r + 0.5f) << 10) |
+ ((unsigned short)(31 * g + 0.5f) << 5) |
+ ((unsigned short)(31 * b + 0.5f) << 0);
+ break;
+ default: UNREACHABLE();
+ }
+ break;
+ case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
+ dest16[i + j * outputPitch / sizeof(unsigned short)] =
+ ((unsigned short)(31 * b + 0.5f) << 0) |
+ ((unsigned short)(63 * g + 0.5f) << 5) |
+ ((unsigned short)(31 * r + 0.5f) << 11);
+ break;
+ default: UNREACHABLE();
+ }
+ break;
+ default: UNREACHABLE();
+ }
+ }
+ }
+
+ systemSurface->UnlockRect();
+
+ systemSurface->Release();
+}
+
+void Context::clear(GLbitfield mask)
+{
+ Framebuffer *framebufferObject = getDrawFramebuffer();
+
+ if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
+ {
+ error(GL_INVALID_FRAMEBUFFER_OPERATION);
+
+ return;
+ }
+
+ egl::Display *display = getDisplay();
+ IDirect3DDevice9 *device = getDevice();
+ 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();
+ D3DSURFACE_DESC desc;
+ depthStencil->GetDesc(&desc);
+
+ unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
+ stencilUnmasked = (0x1 << stencilSize) - 1;
+
+ if (stencilUnmasked != 0x0)
+ {
+ flags |= D3DCLEAR_STENCIL;
+ }
+ }
+ }
+
+ if (mask != 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ 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;
+
+ IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
+
+ D3DSURFACE_DESC desc;
+ renderTarget->GetDesc(&desc);
+
+ bool alphaUnmasked = (es2dx::GetAlphaSize(desc.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 = device->BeginStateBlock();
+ ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+
+ device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+ device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
+ device->SetRenderState(D3DRS_ZENABLE, FALSE);
+ device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+ device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+ device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+ device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
+ device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ device->SetPixelShader(NULL);
+ device->SetVertexShader(NULL);
+ device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
+ device->SetStreamSourceFreq(0, 1);
+
+ hr = device->EndStateBlock(&mMaskedClearSavedState);
+ ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+ }
+
+ ASSERT(mMaskedClearSavedState != NULL);
+
+ if (mMaskedClearSavedState != NULL)
+ {
+ hr = mMaskedClearSavedState->Capture();
+ ASSERT(SUCCEEDED(hr));
+ }
+
+ device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+ device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
+ device->SetRenderState(D3DRS_ZENABLE, FALSE);
+ device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+ device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+ device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+
+ if (flags & D3DCLEAR_TARGET)
+ {
+ device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
+ (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
+ (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
+ (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
+ }
+ else
+ {
+ device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
+ }
+
+ if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
+ {
+ device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+ device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
+ device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
+ device->SetRenderState(D3DRS_STENCILREF, stencil);
+ device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
+ device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
+ device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
+ device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
+ mStencilStateDirty = true;
+ }
+ else
+ {
+ device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ }
+
+ device->SetPixelShader(NULL);
+ device->SetVertexShader(NULL);
+ device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
+ device->SetStreamSourceFreq(0, 1);
+
+ struct Vertex
+ {
+ float x, y, z, w;
+ D3DCOLOR diffuse;
+ };
+
+ Vertex quad[4];
+ quad[0].x = 0.0f;
+ quad[0].y = (float)desc.Height;
+ quad[0].z = 0.0f;
+ quad[0].w = 1.0f;
+ quad[0].diffuse = color;
+
+ quad[1].x = (float)desc.Width;
+ quad[1].y = (float)desc.Height;
+ quad[1].z = 0.0f;
+ quad[1].w = 1.0f;
+ quad[1].diffuse = color;
+
+ quad[2].x = 0.0f;
+ quad[2].y = 0.0f;
+ quad[2].z = 0.0f;
+ quad[2].w = 1.0f;
+ quad[2].diffuse = color;
+
+ quad[3].x = (float)desc.Width;
+ quad[3].y = 0.0f;
+ quad[3].z = 0.0f;
+ quad[3].w = 1.0f;
+ quad[3].diffuse = color;
+
+ display->startScene();
+ device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
+
+ if (flags & D3DCLEAR_ZBUFFER)
+ {
+ device->SetRenderState(D3DRS_ZENABLE, TRUE);
+ device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
+ device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
+ }
+
+ if (mMaskedClearSavedState != NULL)
+ {
+ mMaskedClearSavedState->Apply();
+ }
+ }
+ else if (flags)
+ {
+ device->Clear(0, NULL, flags, color, depth, stencil);
+ }
+}
+
+void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
+{
+ if (!mState.currentProgram)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ egl::Display *display = getDisplay();
+ IDirect3DDevice9 *device = getDevice();
+ D3DPRIMITIVETYPE primitiveType;
+ int primitiveCount;
+
+ if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
+ return error(GL_INVALID_ENUM);
+
+ if (primitiveCount <= 0)
+ {
+ return;
+ }
+
+ if (!applyRenderTarget(false))
+ {
+ return;
+ }
+
+ applyState(mode);
+
+ TranslatedIndexData indexInfo;
+ bool useIndexing;
+ GLenum err = applyVertexBuffer(mode, first, count, &useIndexing, &indexInfo);
+ if (err != GL_NO_ERROR)
+ {
+ return error(err);
+ }
+
+ applyShaders();
+ applyTextures();
+
+ if (!getCurrentProgram()->validateSamplers())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!cullSkipsDraw(mode))
+ {
+ display->startScene();
+ if (useIndexing)
+ {
+ device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/indexInfo.indexSize, primitiveCount);
+ }
+ else
+ {
+ device->DrawPrimitive(primitiveType, 0, primitiveCount);
+ }
+ }
+}
+
+void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
+{
+ if (!mState.currentProgram)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!indices && !mState.elementArrayBuffer)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ egl::Display *display = getDisplay();
+ IDirect3DDevice9 *device = getDevice();
+ D3DPRIMITIVETYPE primitiveType;
+ int primitiveCount;
+
+ if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
+ return error(GL_INVALID_ENUM);
+
+ if (primitiveCount <= 0)
+ {
+ return;
+ }
+
+ if (!applyRenderTarget(false))
+ {
+ return;
+ }
+
+ applyState(mode);
+
+ TranslatedIndexData indexInfo;
+ GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);
+ if (err != GL_NO_ERROR)
+ {
+ return error(err);
+ }
+
+ err = applyVertexBuffer(indexInfo);
+ if (err != GL_NO_ERROR)
+ {
+ return error(err);
+ }
+
+ applyShaders();
+ applyTextures();
+
+ if (!getCurrentProgram()->validateSamplers())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!cullSkipsDraw(mode))
+ {
+ display->startScene();
+ device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/indexInfo.indexSize, primitiveCount);
+ }
+}
+
+void Context::finish()
+{
+ egl::Display *display = getDisplay();
+ IDirect3DDevice9 *device = getDevice();
+ IDirect3DQuery9 *occlusionQuery = NULL;
+
+ HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
+
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+
+ ASSERT(SUCCEEDED(result));
+
+ if (occlusionQuery)
+ {
+ IDirect3DStateBlock9 *savedState = NULL;
+ device->CreateStateBlock(D3DSBT_ALL, &savedState);
+
+ HRESULT result = occlusionQuery->Issue(D3DISSUE_BEGIN);
+ ASSERT(SUCCEEDED(result));
+
+ // Render something outside the render target
+ device->SetStreamSourceFreq(0, 1);
+ device->SetPixelShader(NULL);
+ device->SetVertexShader(NULL);
+ device->SetFVF(D3DFVF_XYZRHW);
+ float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
+ display->startScene();
+ device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
+
+ result = occlusionQuery->Issue(D3DISSUE_END);
+ ASSERT(SUCCEEDED(result));
+
+ while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
+ {
+ // Keep polling, but allow other threads to do something useful first
+ Sleep(0);
+ }
+
+ occlusionQuery->Release();
+
+ if (savedState)
+ {
+ savedState->Apply();
+ savedState->Release();
+ }
+ }
+}
+
+void Context::flush()
+{
+ IDirect3DDevice9 *device = getDevice();
+ IDirect3DQuery9 *eventQuery = NULL;
+
+ HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
+
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+
+ ASSERT(SUCCEEDED(result));
+
+ if (eventQuery)
+ {
+ HRESULT result = eventQuery->Issue(D3DISSUE_END);
+ ASSERT(SUCCEEDED(result));
+
+ result = eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
+ eventQuery->Release();
+
+ if (result == D3DERR_DEVICELOST)
+ {
+ 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;
+}
+
+bool Context::supportsShaderModel3() const
+{
+ return mSupportsShaderModel3;
+}
+
+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::supportsCompressedTextures() const
+{
+ return mSupportsCompressedTextures;
+}
+
+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 < SAMPLER_TYPE_COUNT; type++)
+ {
+ for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
+ {
+ if (mState.samplerTexture[type][sampler].id() == texture)
+ {
+ mState.samplerTexture[type][sampler].set(NULL);
+ }
+ }
+ }
+
+ // [OpenGL ES 2.0.24] section 4.4 page 112:
+ // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
+ // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
+ // image was attached in the currently bound framebuffer.
+
+ Framebuffer *readFramebuffer = getReadFramebuffer();
+ Framebuffer *drawFramebuffer = getDrawFramebuffer();
+
+ if (readFramebuffer)
+ {
+ readFramebuffer->detachTexture(texture);
+ }
+
+ if (drawFramebuffer && drawFramebuffer != readFramebuffer)
+ {
+ drawFramebuffer->detachTexture(texture);
+ }
+}
+
+void Context::detachFramebuffer(GLuint framebuffer)
+{
+ // [OpenGL ES 2.0.24] section 4.4 page 107:
+ // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
+ // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
+
+ if (mState.readFramebuffer == framebuffer)
+ {
+ bindReadFramebuffer(0);
+ }
+
+ if (mState.drawFramebuffer == framebuffer)
+ {
+ bindDrawFramebuffer(0);
+ }
+}
+
+void Context::detachRenderbuffer(GLuint renderbuffer)
+{
+ // [OpenGL ES 2.0.24] section 4.4 page 109:
+ // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
+ // had been executed with the target RENDERBUFFER and name of zero.
+
+ if (mState.renderbuffer.id() == renderbuffer)
+ {
+ bindRenderbuffer(0);
+ }
+
+ // [OpenGL ES 2.0.24] section 4.4 page 111:
+ // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
+ // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
+ // point to which this image was attached in the currently bound framebuffer.
+
+ Framebuffer *readFramebuffer = getReadFramebuffer();
+ Framebuffer *drawFramebuffer = getDrawFramebuffer();
+
+ if (readFramebuffer)
+ {
+ readFramebuffer->detachRenderbuffer(renderbuffer);
+ }
+
+ if (drawFramebuffer && drawFramebuffer != readFramebuffer)
+ {
+ drawFramebuffer->detachRenderbuffer(renderbuffer);
+ }
+}
+
+Texture *Context::getIncompleteTexture(SamplerType type)
+{
+ Texture *t = mIncompleteTextures[type];
+
+ if (t == NULL)
+ {
+ static const GLubyte color[] = { 0, 0, 0, 255 };
+
+ switch (type)
+ {
+ default:
+ UNREACHABLE();
+ // default falls through to SAMPLER_2D
+
+ case SAMPLER_2D:
+ {
+ Texture2D *incomplete2d = new Texture2D(Texture::INCOMPLETE_TEXTURE_ID);
+ incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+ t = incomplete2d;
+ }
+ break;
+
+ case SAMPLER_CUBE:
+ {
+ TextureCubeMap *incompleteCube = new TextureCubeMap(Texture::INCOMPLETE_TEXTURE_ID);
+
+ incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+ incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+ incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+ incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+ incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+ incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+
+ t = incompleteCube;
+ }
+ break;
+ }
+
+ mIncompleteTextures[type] = t;
+ }
+
+ return t;
+}
+
+bool Context::cullSkipsDraw(GLenum drawMode)
+{
+ return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
+}
+
+bool Context::isTriangleMode(GLenum drawMode)
+{
+ switch (drawMode)
+ {
+ case GL_TRIANGLES:
+ case GL_TRIANGLE_FAN:
+ case GL_TRIANGLE_STRIP:
+ return true;
+ case GL_POINTS:
+ case GL_LINES:
+ case GL_LINE_LOOP:
+ case GL_LINE_STRIP:
+ return false;
+ default: UNREACHABLE();
+ }
+
+ return false;
+}
+
+void Context::setVertexAttrib(GLuint index, const GLfloat *values)
+{
+ ASSERT(index < 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->dirtyCurrentValues();
+}
+
+void Context::initExtensionString()
+{
+ mExtensionString += "GL_OES_packed_depth_stencil ";
+ mExtensionString += "GL_EXT_texture_format_BGRA8888 ";
+ mExtensionString += "GL_EXT_read_format_bgra ";
+ mExtensionString += "GL_ANGLE_framebuffer_blit ";
+ mExtensionString += "GL_OES_rgb8_rgba8 ";
+
+ if (supportsCompressedTextures())
+ {
+ mExtensionString += "GL_EXT_texture_compression_dxt1 ";
+ }
+
+ if (getMaxSupportedSamples() != 0)
+ {
+ mExtensionString += "GL_ANGLE_framebuffer_multisample ";
+ }
+
+ if (mBufferBackEnd->supportIntIndices())
+ {
+ mExtensionString += "GL_OES_element_index_uint ";
+ }
+
+ std::string::size_type end = mExtensionString.find_last_not_of(' ');
+ if (end != std::string::npos)
+ {
+ mExtensionString.resize(end+1);
+ }
+}
+
+const char *Context::getExtensionString() const
+{
+ return mExtensionString.c_str();
+}
+
+void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask)
+{
+ IDirect3DDevice9 *device = getDevice();
+
+ 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);
+ }
+
+ 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;
+ }
+
+ // Arguments to StretchRect must be in D3D-style (0-top) coordinates, so we must
+ // flip our Y-values here
+ 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;
+ }
+
+ int readBufferWidth = readFramebuffer->getColorbuffer()->getWidth();
+ int readBufferHeight = readFramebuffer->getColorbuffer()->getHeight();
+ int drawBufferWidth = drawFramebuffer->getColorbuffer()->getWidth();
+ int drawBufferHeight = drawFramebuffer->getColorbuffer()->getHeight();
+
+ 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 < readFramebuffer->getColorbuffer()->getHeight() ||
+ sourceTrimmedRect.right - sourceTrimmedRect.left < readFramebuffer->getColorbuffer()->getWidth() ||
+ destTrimmedRect.bottom - destTrimmedRect.top < drawFramebuffer->getColorbuffer()->getHeight() ||
+ destTrimmedRect.right - destTrimmedRect.left < drawFramebuffer->getColorbuffer()->getWidth() ||
+ sourceTrimmedRect.top != 0 || destTrimmedRect.top != 0 || sourceTrimmedRect.left != 0 || destTrimmedRect.left != 0)
+ {
+ partialBufferCopy = true;
+ }
+
+ if (mask & GL_COLOR_BUFFER_BIT)
+ {
+ if (readFramebuffer->getColorbufferType() != drawFramebuffer->getColorbufferType() ||
+ 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))
+ {
+ DepthStencilbuffer *readDSBuffer = NULL;
+ DepthStencilbuffer *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)
+ {
+ egl::Display *display = getDisplay();
+ display->endScene();
+
+ if (blitRenderTarget)
+ {
+ HRESULT result = device->StretchRect(readFramebuffer->getRenderTarget(), &sourceTrimmedRect,
+ drawFramebuffer->getRenderTarget(), &destTrimmedRect, D3DTEXF_NONE);
+
+ if (FAILED(result))
+ {
+ ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
+ return;
+ }
+ }
+
+ if (blitDepthStencil)
+ {
+ HRESULT result = device->StretchRect(readFramebuffer->getDepthStencil(), NULL, drawFramebuffer->getDepthStencil(), NULL, D3DTEXF_NONE);
+
+ if (FAILED(result))
+ {
+ ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
+ return;
+ }
+ }
+ }
+}
+
+}
+
+extern "C"
+{
+gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext)
+{
+ return new gl::Context(config, shareContext);
+}
+
+void glDestroyContext(gl::Context *context)
+{
+ delete context;
+
+ if (context == gl::getContext())
+ {
+ gl::makeCurrent(NULL, NULL, NULL);
+ }
+}
+
+void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
+{
+ gl::makeCurrent(context, display, surface);
+}
+
+gl::Context *glGetCurrentContext()
+{
+ return gl::getContext();
+}
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Context.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Context.h
new file mode 100644
index 0000000..6bca756
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Context.h
@@ -0,0 +1,480 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Context.h: Defines the gl::Context class, managing all GL state and performing
+// rendering operations. It is the GLES2 specific implementation of EGLContext.
+
+#ifndef LIBGLESV2_CONTEXT_H_
+#define LIBGLESV2_CONTEXT_H_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#define EGLAPI
+#include <EGL/egl.h>
+#include <d3d9.h>
+
+#include <map>
+
+#include "common/angleutils.h"
+#include "libGLESv2/ResourceManager.h"
+#include "libGLESv2/RefCountObject.h"
+
+namespace egl
+{
+class Display;
+class Surface;
+class Config;
+}
+
+namespace gl
+{
+struct TranslatedAttribute;
+struct TranslatedIndexData;
+
+class Buffer;
+class Shader;
+class Program;
+class Texture;
+class Texture2D;
+class TextureCubeMap;
+class Framebuffer;
+class Renderbuffer;
+class RenderbufferStorage;
+class Colorbuffer;
+class Depthbuffer;
+class Stencilbuffer;
+class DepthStencilbuffer;
+class VertexDataManager;
+class IndexDataManager;
+class BufferBackEnd;
+class Blit;
+
+enum
+{
+ MAX_VERTEX_ATTRIBS = 12,
+ MAX_VERTEX_UNIFORM_VECTORS = 128,
+ MAX_VARYING_VECTORS = 8,
+ MAX_COMBINED_TEXTURE_IMAGE_UNITS = 16,
+ MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0,
+ MAX_TEXTURE_IMAGE_UNITS = 16,
+ MAX_FRAGMENT_UNIFORM_VECTORS = 16,
+ MAX_RENDERBUFFER_SIZE = 4096, // FIXME: Verify
+ MAX_DRAW_BUFFERS = 1,
+
+ IMPLEMENTATION_COLOR_READ_FORMAT = GL_RGB,
+ IMPLEMENTATION_COLOR_READ_TYPE = GL_UNSIGNED_SHORT_5_6_5
+};
+
+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;
+const float ALIASED_POINT_SIZE_RANGE_MAX_SM3 = 64.0f;
+
+struct Color
+{
+ float red;
+ float green;
+ float blue;
+ float alpha;
+};
+
+// Helper structure describing a single vertex attribute
+class AttributeState
+{
+ public:
+ AttributeState()
+ : mType(GL_FLOAT), mSize(0), mNormalized(false), mStride(0), mPointer(NULL), mEnabled(false)
+ {
+ mCurrentValue[0] = 0;
+ mCurrentValue[1] = 0;
+ mCurrentValue[2] = 0;
+ mCurrentValue[3] = 1;
+ }
+
+ // From VertexArrayPointer
+ GLenum mType;
+ GLint mSize;
+ bool mNormalized;
+ GLsizei mStride; // 0 means natural stride
+ const void *mPointer;
+
+ BindingPointer<Buffer> mBoundBuffer; // Captured when VertexArrayPointer is called.
+
+ bool mEnabled; // From Enable/DisableVertexAttribArray
+
+ float mCurrentValue[4]; // From VertexAttrib4f
+};
+
+// 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;
+
+ GLint viewportX;
+ GLint viewportY;
+ GLsizei viewportWidth;
+ GLsizei viewportHeight;
+ float zNear;
+ float zFar;
+
+ GLint scissorX;
+ GLint scissorY;
+ GLsizei scissorWidth;
+ GLsizei scissorHeight;
+
+ bool colorMaskRed;
+ bool colorMaskGreen;
+ bool colorMaskBlue;
+ bool colorMaskAlpha;
+ bool depthMask;
+
+ int activeSampler; // Active texture unit selector - GL_TEXTURE0
+ BindingPointer<Buffer> arrayBuffer;
+ BindingPointer<Buffer> elementArrayBuffer;
+ BindingPointer<Texture> texture2D;
+ BindingPointer<Texture> textureCubeMap;
+ GLuint readFramebuffer;
+ GLuint drawFramebuffer;
+ BindingPointer<Renderbuffer> renderbuffer;
+ GLuint currentProgram;
+
+ AttributeState vertexAttribute[MAX_VERTEX_ATTRIBS];
+ BindingPointer<Texture> samplerTexture[SAMPLER_TYPE_COUNT][MAX_TEXTURE_IMAGE_UNITS];
+
+ GLint unpackAlignment;
+ GLint packAlignment;
+};
+
+class Context
+{
+ public:
+ Context(const egl::Config *config, const gl::Context *shareContext);
+
+ ~Context();
+
+ void makeCurrent(egl::Display *display, egl::Surface *surface);
+
+ void markAllStateDirty();
+
+ // State manipulation
+ void setClearColor(float red, float green, float blue, float alpha);
+
+ void setClearDepth(float depth);
+
+ void setClearStencil(int stencil);
+
+ void setCullFace(bool enabled);
+ bool isCullFaceEnabled() const;
+
+ void setCullMode(GLenum mode);
+
+ void setFrontFace(GLenum front);
+
+ void setDepthTest(bool enabled);
+ bool isDepthTestEnabled() const;
+
+ void setDepthFunc(GLenum depthFunc);
+
+ void setDepthRange(float zNear, float zFar);
+
+ void setBlend(bool enabled);
+ bool isBlendEnabled() const;
+
+ void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha);
+ void setBlendColor(float red, float green, float blue, float alpha);
+ void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation);
+
+ void setStencilTest(bool enabled);
+ bool isStencilTestEnabled() const;
+
+ void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask);
+ void setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask);
+ void setStencilWritemask(GLuint stencilWritemask);
+ void setStencilBackWritemask(GLuint stencilBackWritemask);
+ void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass);
+ void setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass);
+
+ void setPolygonOffsetFill(bool enabled);
+ bool isPolygonOffsetFillEnabled() const;
+
+ void setPolygonOffsetParams(GLfloat factor, GLfloat units);
+
+ void setSampleAlphaToCoverage(bool enabled);
+ bool isSampleAlphaToCoverageEnabled() const;
+
+ void setSampleCoverage(bool enabled);
+ bool isSampleCoverageEnabled() const;
+
+ void setSampleCoverageParams(GLclampf value, bool invert);
+
+ void setScissorTest(bool enabled);
+ bool isScissorTestEnabled() const;
+
+ void setDither(bool enabled);
+ bool isDitherEnabled() const;
+
+ void setLineWidth(GLfloat width);
+
+ void setGenerateMipmapHint(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(int active);
+
+ GLuint getReadFramebufferHandle() const;
+ GLuint getDrawFramebufferHandle() const;
+ GLuint getRenderbufferHandle() const;
+
+ GLuint getArrayBufferHandle() const;
+
+ void setVertexAttribEnabled(unsigned int attribNum, bool enabled);
+ const AttributeState &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 AttributeState *getVertexAttribBlock();
+
+ void setUnpackAlignment(GLint alignment);
+ GLint getUnpackAlignment() const;
+
+ void setPackAlignment(GLint alignment);
+ GLint getPackAlignment() const;
+
+ // These create and destroy methods are merely pass-throughs to
+ // ResourceManager, which owns these object types
+ GLuint createBuffer();
+ GLuint createShader(GLenum type);
+ GLuint createProgram();
+ GLuint createTexture();
+ GLuint createRenderbuffer();
+
+ void deleteBuffer(GLuint buffer);
+ void deleteShader(GLuint shader);
+ void deleteProgram(GLuint program);
+ void deleteTexture(GLuint texture);
+ void deleteRenderbuffer(GLuint renderbuffer);
+
+ // Framebuffers are owned by the Context, so these methods do not pass through
+ GLuint createFramebuffer();
+ void deleteFramebuffer(GLuint framebuffer);
+
+ 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 setFramebufferZero(Framebuffer *framebuffer);
+
+ void setRenderbufferStorage(RenderbufferStorage *renderbuffer);
+
+ void setVertexAttrib(GLuint index, const GLfloat *values);
+
+ Buffer *getBuffer(GLuint handle);
+ Shader *getShader(GLuint handle);
+ Program *getProgram(GLuint handle);
+ Texture *getTexture(GLuint handle);
+ Framebuffer *getFramebuffer(GLuint handle);
+ Renderbuffer *getRenderbuffer(GLuint handle);
+
+ Buffer *getArrayBuffer();
+ Buffer *getElementArrayBuffer();
+ Program *getCurrentProgram();
+ Texture2D *getTexture2D();
+ TextureCubeMap *getTextureCubeMap();
+ Texture *getSamplerTexture(unsigned int sampler, SamplerType 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);
+
+ bool applyRenderTarget(bool ignoreViewport);
+ void applyState(GLenum drawMode);
+ GLenum applyVertexBuffer(GLenum mode, GLint first, GLsizei count, bool *useIndexing, TranslatedIndexData *indexInfo);
+ GLenum applyVertexBuffer(const TranslatedIndexData &indexInfo);
+ GLenum applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
+ GLenum applyCountingIndexBuffer(GLenum mode, GLenum count, TranslatedIndexData *indexInfo);
+ void applyShaders();
+ void applyTextures();
+
+ void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
+ void clear(GLbitfield mask);
+ void drawArrays(GLenum mode, GLint first, GLsizei count);
+ void drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices);
+ void finish();
+ void flush();
+
+ void recordInvalidEnum();
+ void recordInvalidValue();
+ void recordInvalidOperation();
+ void recordOutOfMemory();
+ void recordInvalidFramebufferOperation();
+
+ GLenum getError();
+
+ bool supportsShaderModel3() const;
+ GLsizei getMaxSupportedSamples() const;
+ int getNearestSupportedSamples(D3DFORMAT format, int requested) const;
+ const char *getExtensionString() const;
+ bool supportsCompressedTextures() 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);
+
+ void lookupAttributeMapping(TranslatedAttribute *attributes);
+
+ void detachBuffer(GLuint buffer);
+ void detachTexture(GLuint texture);
+ void detachFramebuffer(GLuint framebuffer);
+ void detachRenderbuffer(GLuint renderbuffer);
+
+ Texture *getIncompleteTexture(SamplerType type);
+
+ bool cullSkipsDraw(GLenum drawMode);
+ bool isTriangleMode(GLenum drawMode);
+
+ const egl::Config *const mConfig;
+
+ State mState;
+
+ Texture2D *mTexture2DZero;
+ TextureCubeMap *mTextureCubeMapZero;
+
+ Colorbuffer *mColorbufferZero;
+ DepthStencilbuffer *mDepthStencilbufferZero;
+
+ typedef std::map<GLuint, Framebuffer*> FramebufferMap;
+ FramebufferMap mFramebufferMap;
+
+ void initExtensionString();
+ std::string mExtensionString;
+
+ BufferBackEnd *mBufferBackEnd;
+ VertexDataManager *mVertexDataManager;
+ IndexDataManager *mIndexDataManager;
+
+ Blit *mBlit;
+
+ Texture *mIncompleteTextures[SAMPLER_TYPE_COUNT];
+
+ // Recorded errors
+ bool mInvalidEnum;
+ bool mInvalidValue;
+ bool mInvalidOperation;
+ bool mOutOfMemory;
+ bool mInvalidFramebufferOperation;
+
+ bool mHasBeenCurrent;
+
+ unsigned int mAppliedProgram;
+ unsigned int mAppliedRenderTargetSerial;
+ unsigned int mAppliedDepthbufferSerial;
+ unsigned int mAppliedStencilbufferSerial;
+
+ bool mSupportsShaderModel3;
+ std::map<D3DFORMAT, bool *> mMultiSampleSupport;
+ GLsizei mMaxSupportedSamples;
+ bool mSupportsCompressedTextures;
+
+ // 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;
+};
+}
+
+extern "C"
+{
+// Exported functions for use by EGL
+gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext);
+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);
+}
+
+#endif // INCLUDE_CONTEXT_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.cpp
new file mode 100644
index 0000000..5c4bc99
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.cpp
@@ -0,0 +1,455 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// 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);
+}
+
+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 (IsTextureTarget(type))
+ {
+ buffer = context->getTexture(handle)->getColorbuffer(type);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ return buffer;
+}
+
+void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
+{
+ mColorbufferType = type;
+ mColorbufferPointer.set(lookupRenderbuffer(type, colorbuffer));
+}
+
+void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
+{
+ mDepthbufferType = type;
+ mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
+}
+
+void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
+{
+ mStencilbufferType = type;
+ mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
+}
+
+void Framebuffer::detachTexture(GLuint texture)
+{
+ if (mColorbufferPointer.id() == texture && IsTextureTarget(mColorbufferType))
+ {
+ mColorbufferType = GL_NONE;
+ mColorbufferPointer.set(NULL);
+ }
+
+ if (mDepthbufferPointer.id() == texture && IsTextureTarget(mDepthbufferType))
+ {
+ mDepthbufferType = GL_NONE;
+ mDepthbufferPointer.set(NULL);
+ }
+
+ if (mStencilbufferPointer.id() == texture && IsTextureTarget(mStencilbufferType))
+ {
+ mStencilbufferType = GL_NONE;
+ mStencilbufferPointer.set(NULL);
+ }
+}
+
+void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
+{
+ if (mColorbufferPointer.id() == renderbuffer && mColorbufferType == GL_RENDERBUFFER)
+ {
+ mColorbufferType = GL_NONE;
+ mColorbufferPointer.set(NULL);
+ }
+
+ if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
+ {
+ mDepthbufferType = GL_NONE;
+ mDepthbufferPointer.set(NULL);
+ }
+
+ if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
+ {
+ mStencilbufferType = GL_NONE;
+ mStencilbufferPointer.set(NULL);
+ }
+}
+
+unsigned int Framebuffer::getRenderTargetSerial()
+{
+ Renderbuffer *colorbuffer = mColorbufferPointer.get();
+
+ if (colorbuffer)
+ {
+ return colorbuffer->getSerial();
+ }
+
+ return 0;
+}
+
+IDirect3DSurface9 *Framebuffer::getRenderTarget()
+{
+ Renderbuffer *colorbuffer = mColorbufferPointer.get();
+
+ if (colorbuffer)
+ {
+ return colorbuffer->getRenderTarget();
+ }
+
+ return NULL;
+}
+
+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;
+}
+
+Colorbuffer *Framebuffer::getColorbuffer()
+{
+ Renderbuffer *rb = mColorbufferPointer.get();
+
+ if (rb != NULL && rb->isColorbuffer())
+ {
+ return static_cast<Colorbuffer*>(rb->getStorage());
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+DepthStencilbuffer *Framebuffer::getDepthbuffer()
+{
+ Renderbuffer *rb = mDepthbufferPointer.get();
+
+ if (rb != NULL && rb->isDepthbuffer())
+ {
+ return static_cast<DepthStencilbuffer*>(rb->getStorage());
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+DepthStencilbuffer *Framebuffer::getStencilbuffer()
+{
+ Renderbuffer *rb = mStencilbufferPointer.get();
+
+ if (rb != NULL && rb->isStencilbuffer())
+ {
+ return static_cast<DepthStencilbuffer*>(rb->getStorage());
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+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)
+ {
+ DepthStencilbuffer *stencilbufferObject = getStencilbuffer();
+
+ if (stencilbufferObject)
+ {
+ return stencilbufferObject->getStencilSize() > 0;
+ }
+ }
+
+ return false;
+}
+
+bool Framebuffer::isMultisample()
+{
+ // If the framebuffer is not complete, attachment samples may be mismatched, and it
+ // cannot be used as a multisample framebuffer. If it is complete, it is required to
+ // have a color attachment, and all its attachments must have the same number of samples,
+ // so the number of samples for the colorbuffer will indicate whether the framebuffer is
+ // multisampled.
+ if (completeness() == GL_FRAMEBUFFER_COMPLETE && getColorbuffer()->getSamples() > 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+GLenum Framebuffer::completeness()
+{
+ int width = 0;
+ int height = 0;
+ int samples = -1;
+
+ if (mColorbufferType != GL_NONE)
+ {
+ Colorbuffer *colorbuffer = getColorbuffer();
+
+ if (!colorbuffer)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ if (IsTextureTarget(mColorbufferType))
+ {
+ if (IsCompressed(colorbuffer->getFormat()))
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
+ }
+
+ width = colorbuffer->getWidth();
+ height = colorbuffer->getHeight();
+ samples = colorbuffer->getSamples();
+ }
+ else
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
+ }
+
+ DepthStencilbuffer *depthbuffer = NULL;
+ DepthStencilbuffer *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 (width == 0)
+ {
+ width = depthbuffer->getWidth();
+ height = depthbuffer->getHeight();
+ }
+ else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+ }
+
+ if (samples == -1)
+ {
+ samples = depthbuffer->getSamples();
+ }
+ else if (samples != depthbuffer->getSamples())
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+ }
+
+ if (IsTextureTarget(mDepthbufferType))
+ {
+ if (IsCompressed(depthbuffer->getFormat()))
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
+ }
+ }
+
+ 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 (width == 0)
+ {
+ width = stencilbuffer->getWidth();
+ height = stencilbuffer->getHeight();
+ }
+ else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+ }
+
+ if (samples == -1)
+ {
+ samples = stencilbuffer->getSamples();
+ }
+ else if (samples != stencilbuffer->getSamples())
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+ }
+
+ if (IsTextureTarget(mStencilbufferType))
+ {
+ if (IsCompressed(stencilbuffer->getFormat()))
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
+ }
+ }
+
+ if (mDepthbufferType == GL_RENDERBUFFER && mStencilbufferType == GL_RENDERBUFFER)
+ {
+ if (depthbuffer->getFormat() != GL_DEPTH24_STENCIL8_OES ||
+ stencilbuffer->getFormat() != GL_DEPTH24_STENCIL8_OES ||
+ depthbuffer->getSerial() != stencilbuffer->getSerial())
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
+ }
+
+ return GL_FRAMEBUFFER_COMPLETE;
+}
+
+DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *color, DepthStencilbuffer *depthStencil)
+{
+ mColorbufferType = GL_RENDERBUFFER;
+ mDepthbufferType = GL_RENDERBUFFER;
+ mStencilbufferType = GL_RENDERBUFFER;
+
+ mColorbufferPointer.set(new Renderbuffer(0, color));
+
+ Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
+ mDepthbufferPointer.set(depthStencilRenderbuffer);
+ mStencilbufferPointer.set(depthStencilRenderbuffer);
+}
+
+int Framebuffer::getSamples()
+{
+ if (completeness() == GL_FRAMEBUFFER_COMPLETE)
+ {
+ return getColorbuffer()->getSamples();
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+GLenum DefaultFramebuffer::completeness()
+{
+ return GL_FRAMEBUFFER_COMPLETE;
+}
+
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.h
new file mode 100644
index 0000000..0995145
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.h
@@ -0,0 +1,96 @@
+//
+// 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 "libGLESv2/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();
+
+ Colorbuffer *getColorbuffer();
+ DepthStencilbuffer *getDepthbuffer();
+ DepthStencilbuffer *getStencilbuffer();
+
+ GLenum getColorbufferType();
+ GLenum getDepthbufferType();
+ GLenum getStencilbufferType();
+
+ GLuint getColorbufferHandle();
+ GLuint getDepthbufferHandle();
+ GLuint getStencilbufferHandle();
+
+ bool hasStencil();
+ bool isMultisample();
+ int getSamples();
+
+ virtual GLenum completeness();
+
+ protected:
+ GLenum mColorbufferType;
+ BindingPointer<Renderbuffer> mColorbufferPointer;
+
+ GLenum mDepthbufferType;
+ BindingPointer<Renderbuffer> mDepthbufferPointer;
+
+ GLenum mStencilbufferType;
+ BindingPointer<Renderbuffer> mStencilbufferPointer;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Framebuffer);
+
+ Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle) const;
+};
+
+class DefaultFramebuffer : public Framebuffer
+{
+ public:
+ DefaultFramebuffer(Colorbuffer *color, DepthStencilbuffer *depthStencil);
+
+ virtual GLenum completeness();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DefaultFramebuffer);
+};
+
+}
+
+#endif // LIBGLESV2_FRAMEBUFFER_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Program.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Program.cpp
new file mode 100644
index 0000000..a32bc9f
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Program.cpp
@@ -0,0 +1,2806 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Program.cpp: Implements the gl::Program class. Implements GL program objects
+// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
+
+#include "libGLESv2/Program.h"
+
+#include "common/debug.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/Shader.h"
+#include "libGLESv2/utilities.h"
+
+namespace gl
+{
+unsigned int Program::mCurrentSerial = 1;
+
+std::string str(int i)
+{
+ char buffer[20];
+ sprintf(buffer, "%d", i);
+ return buffer;
+}
+
+Uniform::Uniform(GLenum type, const std::string &name, unsigned int arraySize) : type(type), name(name), arraySize(arraySize)
+{
+ int bytes = UniformTypeSize(type) * arraySize;
+ data = new unsigned char[bytes];
+ memset(data, 0, bytes);
+ dirty = true;
+ handlesSet = false;
+}
+
+Uniform::~Uniform()
+{
+ delete[] data;
+}
+
+UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index)
+ : name(name), element(element), index(index)
+{
+}
+
+Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle)
+{
+ mFragmentShader = NULL;
+ mVertexShader = NULL;
+
+ mPixelExecutable = NULL;
+ mVertexExecutable = NULL;
+ mConstantTablePS = NULL;
+ mConstantTableVS = NULL;
+
+ mInfoLog = NULL;
+ mValidated = false;
+
+ unlink();
+
+ mDeleteStatus = false;
+
+ mRefCount = 0;
+
+ mSerial = issueSerial();
+}
+
+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();
+
+ unlink();
+
+ return true;
+}
+
+int Program::getAttachedShadersCount() const
+{
+ return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
+}
+
+IDirect3DPixelShader9 *Program::getPixelShader()
+{
+ return mPixelExecutable;
+}
+
+IDirect3DVertexShader9 *Program::getVertexShader()
+{
+ return mVertexExecutable;
+}
+
+void Program::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);
+ }
+}
+
+GLuint Program::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 Program::getSemanticIndex(int attributeIndex)
+{
+ if (attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS)
+ {
+ return mSemanticIndex[attributeIndex];
+ }
+
+ return -1;
+}
+
+// Returns the index of the texture unit corresponding to a Direct3D 9 sampler
+// index referenced in the compiled HLSL shader
+GLint Program::getSamplerMapping(unsigned int samplerIndex)
+{
+ assert(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]));
+
+ GLint logicalTextureUnit = -1;
+
+ if (mSamplers[samplerIndex].active)
+ {
+ logicalTextureUnit = mSamplers[samplerIndex].logicalTextureUnit;
+ }
+
+ if (logicalTextureUnit < MAX_TEXTURE_IMAGE_UNITS)
+ {
+ return logicalTextureUnit;
+ }
+
+ return -1;
+}
+
+SamplerType Program::getSamplerType(unsigned int samplerIndex)
+{
+ assert(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]));
+ assert(mSamplers[samplerIndex].active);
+
+ return mSamplers[samplerIndex].type;
+}
+
+bool Program::isSamplerDirty(unsigned int samplerIndex) const
+{
+ if (samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]))
+ {
+ return mSamplers[samplerIndex].dirty;
+ }
+ else UNREACHABLE();
+
+ return false;
+}
+
+void Program::setSamplerDirty(unsigned int samplerIndex, bool dirty)
+{
+ if (samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]))
+ {
+ mSamplers[samplerIndex].dirty = dirty;
+ }
+ else UNREACHABLE();
+}
+
+GLint Program::getUniformLocation(const char *name, bool decorated)
+{
+ std::string nameStr(name);
+ int subscript = 0;
+ size_t beginB = nameStr.find('[');
+ size_t endB = nameStr.find(']');
+ if (beginB != std::string::npos && endB != std::string::npos)
+ {
+ std::string subscrStr = nameStr.substr(beginB + 1, beginB - endB - 1);
+ nameStr.erase(beginB);
+ subscript = atoi(subscrStr.c_str());
+ }
+
+ if (!decorated)
+ {
+ nameStr = decorate(nameStr);
+ }
+
+ unsigned int numUniforms = mUniformIndex.size();
+ for (unsigned int location = 0; location < numUniforms; location++)
+ {
+ if (mUniformIndex[location].name == nameStr &&
+ mUniformIndex[location].element == subscript)
+ {
+ return location;
+ }
+ }
+
+ return -1;
+}
+
+bool Program::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);
+
+ memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat),
+ v, sizeof(GLfloat) * 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 = new GLboolean[count];
+
+ for (int i = 0; i < count; ++i)
+ {
+ if (v[i] == 0.0f)
+ {
+ boolParams[i] = GL_FALSE;
+ }
+ else
+ {
+ boolParams[i] = GL_TRUE;
+ }
+ }
+
+ memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean),
+ boolParams, sizeof(GLboolean) * count);
+
+ delete [] boolParams;
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool Program::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);
+
+ memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 2,
+ v, 2 * sizeof(GLfloat) * 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 = new GLboolean[count * 2];
+
+ for (int i = 0; i < count * 2; ++i)
+ {
+ if (v[i] == 0.0f)
+ {
+ boolParams[i] = GL_FALSE;
+ }
+ else
+ {
+ boolParams[i] = GL_TRUE;
+ }
+ }
+
+ memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 2,
+ boolParams, 2 * sizeof(GLboolean) * count);
+
+ delete [] boolParams;
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool Program::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);
+
+ memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 3,
+ v, 3 * sizeof(GLfloat) * 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 = new GLboolean[count * 3];
+
+ for (int i = 0; i < count * 3; ++i)
+ {
+ if (v[i] == 0.0f)
+ {
+ boolParams[i] = GL_FALSE;
+ }
+ else
+ {
+ boolParams[i] = GL_TRUE;
+ }
+ }
+
+ memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 3,
+ boolParams, 3 * sizeof(GLboolean) * count);
+
+ delete [] boolParams;
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool Program::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 = new GLboolean[count * 4];
+
+ for (int i = 0; i < count * 4; ++i)
+ {
+ if (v[i] == 0.0f)
+ {
+ boolParams[i] = GL_FALSE;
+ }
+ else
+ {
+ boolParams[i] = GL_TRUE;
+ }
+ }
+
+ memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 4,
+ boolParams, 4 * sizeof(GLboolean) * count);
+
+ delete [] boolParams;
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool Program::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);
+
+ memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4,
+ value, 4 * sizeof(GLfloat) * count);
+
+ return true;
+}
+
+bool Program::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
+{
+ if (location < 0 || location >= (int)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);
+
+ memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 9,
+ value, 9 * sizeof(GLfloat) * count);
+
+ return true;
+}
+
+bool Program::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
+{
+ if (location < 0 || location >= (int)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);
+
+ memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16,
+ value, 16 * sizeof(GLfloat) * count);
+
+ return true;
+}
+
+bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+ if (location < 0 || location >= (int)mUniformIndex.size())
+ {
+ return false;
+ }
+
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+ targetUniform->dirty = true;
+
+ if (targetUniform->type == GL_INT)
+ {
+ 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 = new GLboolean[count];
+
+ for (int i = 0; i < count; ++i)
+ {
+ if (v[i] == 0)
+ {
+ boolParams[i] = GL_FALSE;
+ }
+ else
+ {
+ boolParams[i] = GL_TRUE;
+ }
+ }
+
+ memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean),
+ boolParams, sizeof(GLboolean) * count);
+
+ delete [] boolParams;
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+ if (location < 0 || location >= (int)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 = new GLboolean[count * 2];
+
+ for (int i = 0; i < count * 2; ++i)
+ {
+ if (v[i] == 0)
+ {
+ boolParams[i] = GL_FALSE;
+ }
+ else
+ {
+ boolParams[i] = GL_TRUE;
+ }
+ }
+
+ memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 2,
+ boolParams, 2 * sizeof(GLboolean) * count);
+
+ delete [] boolParams;
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+ if (location < 0 || location >= (int)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 = new GLboolean[count * 3];
+
+ for (int i = 0; i < count * 3; ++i)
+ {
+ if (v[i] == 0)
+ {
+ boolParams[i] = GL_FALSE;
+ }
+ else
+ {
+ boolParams[i] = GL_TRUE;
+ }
+ }
+
+ memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 3,
+ boolParams, 3 * sizeof(GLboolean) * count);
+
+ delete [] boolParams;
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+ if (location < 0 || location >= (int)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 = new GLboolean[count * 4];
+
+ for (int i = 0; i < count * 4; ++i)
+ {
+ if (v[i] == 0)
+ {
+ boolParams[i] = GL_FALSE;
+ }
+ else
+ {
+ boolParams[i] = GL_TRUE;
+ }
+ }
+
+ memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 4,
+ boolParams, 4 * sizeof(GLboolean) * count);
+
+ delete [] boolParams;
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool Program::getUniformfv(GLint location, GLfloat *params)
+{
+ if (location < 0 || location >= (int)mUniformIndex.size())
+ {
+ return false;
+ }
+
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ unsigned int count = UniformComponentCount(targetUniform->type);
+
+ switch (UniformComponentType(targetUniform->type))
+ {
+ case GL_BOOL:
+ {
+ GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * count;
+
+ for (unsigned int i = 0; i < count; ++i)
+ {
+ params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
+ }
+ }
+ break;
+ case GL_FLOAT:
+ memcpy(params, targetUniform->data + mUniformIndex[location].element * count * sizeof(GLfloat),
+ count * sizeof(GLfloat));
+ break;
+ case GL_INT:
+ {
+ GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * count;
+
+ for (unsigned int i = 0; i < count; ++i)
+ {
+ params[i] = (float)intParams[i];
+ }
+ }
+ break;
+ default: UNREACHABLE();
+ }
+
+ return true;
+}
+
+bool Program::getUniformiv(GLint location, GLint *params)
+{
+ if (location < 0 || location >= (int)mUniformIndex.size())
+ {
+ return false;
+ }
+
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ unsigned int count = UniformComponentCount(targetUniform->type);
+
+ switch (UniformComponentType(targetUniform->type))
+ {
+ case GL_BOOL:
+ {
+ GLboolean *boolParams = targetUniform->data + mUniformIndex[location].element * count;
+
+ for (unsigned int i = 0; i < count; ++i)
+ {
+ params[i] = (GLint)boolParams[i];
+ }
+ }
+ break;
+ case GL_FLOAT:
+ {
+ GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * count;
+
+ for (unsigned int i = 0; i < count; ++i)
+ {
+ params[i] = (GLint)floatParams[i];
+ }
+ }
+ break;
+ case GL_INT:
+ memcpy(params, targetUniform->data + mUniformIndex[location].element * count * sizeof(GLint),
+ count * sizeof(GLint));
+ break;
+ default: UNREACHABLE();
+ }
+
+ return true;
+}
+
+void Program::dirtyAllUniforms()
+{
+ unsigned int numUniforms = mUniforms.size();
+ for (unsigned int index = 0; index < numUniforms; index++)
+ {
+ mUniforms[index]->dirty = true;
+ }
+}
+
+void Program::dirtyAllSamplers()
+{
+ for (unsigned int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; ++index)
+ {
+ mSamplers[index].dirty = true;
+ }
+}
+
+// Applies all the uniforms set for this program object to the Direct3D 9 device
+void Program::applyUniforms()
+{
+ unsigned int numUniforms = mUniformIndex.size();
+ for (unsigned int location = 0; location < numUniforms; location++)
+ {
+ if (mUniformIndex[location].element != 0)
+ {
+ continue;
+ }
+
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ 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: applyUniform1bv(location, arraySize, b); break;
+ case GL_BOOL_VEC2: applyUniform2bv(location, arraySize, b); break;
+ case GL_BOOL_VEC3: applyUniform3bv(location, arraySize, b); break;
+ case GL_BOOL_VEC4: applyUniform4bv(location, arraySize, b); break;
+ case GL_FLOAT: applyUniform1fv(location, arraySize, f); break;
+ case GL_FLOAT_VEC2: applyUniform2fv(location, arraySize, f); break;
+ case GL_FLOAT_VEC3: applyUniform3fv(location, arraySize, f); break;
+ case GL_FLOAT_VEC4: applyUniform4fv(location, arraySize, f); break;
+ case GL_FLOAT_MAT2: applyUniformMatrix2fv(location, arraySize, f); break;
+ case GL_FLOAT_MAT3: applyUniformMatrix3fv(location, arraySize, f); break;
+ case GL_FLOAT_MAT4: applyUniformMatrix4fv(location, arraySize, f); break;
+ case GL_INT: applyUniform1iv(location, arraySize, i); break;
+ case GL_INT_VEC2: applyUniform2iv(location, arraySize, i); break;
+ case GL_INT_VEC3: applyUniform3iv(location, arraySize, i); break;
+ case GL_INT_VEC4: applyUniform4iv(location, arraySize, i); break;
+ default:
+ UNREACHABLE();
+ }
+
+ targetUniform->dirty = false;
+ }
+ }
+}
+
+// Compiles the HLSL code of the attached shaders into executable binaries
+ID3DXBuffer *Program::compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable)
+{
+ if (!hlsl)
+ {
+ return NULL;
+ }
+
+ ID3DXBuffer *binary = NULL;
+ ID3DXBuffer *errorMessage = NULL;
+
+ HRESULT result = D3DXCompileShader(hlsl, (UINT)strlen(hlsl), NULL, NULL, "main", profile, 0, &binary, &errorMessage, constantTable);
+
+ if (SUCCEEDED(result))
+ {
+ return binary;
+ }
+
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+ {
+ return error(GL_OUT_OF_MEMORY, (ID3DXBuffer*)NULL);
+ }
+
+ if (errorMessage)
+ {
+ const char *message = (const char*)errorMessage->GetBufferPointer();
+
+ appendToInfoLog("%s\n", message);
+ TRACE("\n%s", hlsl);
+ TRACE("\n%s", message);
+ }
+
+ 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 Program::packVaryings(const Varying *packing[][4])
+{
+ for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.end(); varying++)
+ {
+ int n = VariableRowCount(varying->type) * varying->size;
+ int m = VariableColumnCount(varying->type);
+ bool success = false;
+
+ if (m == 2 || m == 3 || m == 4)
+ {
+ for (int r = 0; r <= MAX_VARYING_VECTORS - n && !success; r++)
+ {
+ bool available = true;
+
+ for (int y = 0; y < n && available; y++)
+ {
+ for (int x = 0; x < m && available; x++)
+ {
+ if (packing[r + y][x])
+ {
+ available = false;
+ }
+ }
+ }
+
+ if (available)
+ {
+ varying->reg = r;
+ varying->col = 0;
+
+ for (int y = 0; y < n; y++)
+ {
+ for (int x = 0; x < m; x++)
+ {
+ packing[r + y][x] = &*varying;
+ }
+ }
+
+ success = true;
+ }
+ }
+
+ if (!success && m == 2)
+ {
+ for (int r = MAX_VARYING_VECTORS - n; r >= 0 && !success; r--)
+ {
+ bool available = true;
+
+ for (int y = 0; y < n && available; y++)
+ {
+ for (int x = 2; x < 4 && available; x++)
+ {
+ if (packing[r + y][x])
+ {
+ available = false;
+ }
+ }
+ }
+
+ if (available)
+ {
+ varying->reg = r;
+ varying->col = 2;
+
+ for (int y = 0; y < n; y++)
+ {
+ for (int x = 2; x < 4; x++)
+ {
+ packing[r + y][x] = &*varying;
+ }
+ }
+
+ success = true;
+ }
+ }
+ }
+ }
+ else if (m == 1)
+ {
+ int space[4] = {0};
+
+ for (int y = 0; y < MAX_VARYING_VECTORS; y++)
+ {
+ for (int x = 0; x < 4; x++)
+ {
+ space[x] += packing[y][x] ? 0 : 1;
+ }
+ }
+
+ int column = 0;
+
+ for (int x = 0; x < 4; x++)
+ {
+ if (space[x] > n && space[x] < space[column])
+ {
+ column = x;
+ }
+ }
+
+ if (space[column] > n)
+ {
+ for (int r = 0; r < MAX_VARYING_VECTORS; r++)
+ {
+ if (!packing[r][column])
+ {
+ varying->reg = r;
+
+ for (int y = r; y < r + n; y++)
+ {
+ packing[y][column] = &*varying;
+ }
+
+ break;
+ }
+ }
+
+ varying->col = column;
+
+ success = true;
+ }
+ }
+ else UNREACHABLE();
+
+ if (!success)
+ {
+ appendToInfoLog("Could not pack varying %s", varying->name.c_str());
+
+ return -1;
+ }
+ }
+
+ // Return the number of used registers
+ int registers = 0;
+
+ for (int r = 0; r < MAX_VARYING_VECTORS; r++)
+ {
+ if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
+ {
+ registers++;
+ }
+ }
+
+ return registers;
+}
+
+bool Program::linkVaryings()
+{
+ if (mPixelHLSL.empty() || mVertexHLSL.empty())
+ {
+ return false;
+ }
+
+ const Varying *packing[MAX_VARYING_VECTORS][4] = {NULL};
+ int registers = packVaryings(packing);
+
+ if (registers < 0)
+ {
+ return false;
+ }
+
+ if (registers == MAX_VARYING_VECTORS && mFragmentShader->mUsesFragCoord)
+ {
+ appendToInfoLog("No varying registers left to support gl_FragCoord");
+
+ return false;
+ }
+
+ for (VaryingList::iterator input = mFragmentShader->varyings.begin(); input != mFragmentShader->varyings.end(); input++)
+ {
+ bool matched = false;
+
+ for (VaryingList::iterator output = mVertexShader->varyings.begin(); output != mVertexShader->varyings.end(); output++)
+ {
+ if (output->name == input->name)
+ {
+ if (output->type != input->type || output->size != input->size)
+ {
+ appendToInfoLog("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str());
+
+ return false;
+ }
+
+ output->reg = input->reg;
+ output->col = input->col;
+
+ matched = true;
+ break;
+ }
+ }
+
+ if (!matched)
+ {
+ appendToInfoLog("Fragment varying varying %s does not match any vertex varying", input->name.c_str());
+
+ return false;
+ }
+ }
+
+ Context *context = getContext();
+ bool sm3 = context->supportsShaderModel3();
+ std::string varyingSemantic = (sm3 ? "COLOR" : "TEXCOORD");
+
+ mVertexHLSL += "struct VS_INPUT\n"
+ "{\n";
+
+ int semanticIndex = 0;
+ for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
+ {
+ switch (attribute->type)
+ {
+ case GL_FLOAT: mVertexHLSL += " float "; break;
+ case GL_FLOAT_VEC2: mVertexHLSL += " float2 "; break;
+ case GL_FLOAT_VEC3: mVertexHLSL += " float3 "; break;
+ case GL_FLOAT_VEC4: mVertexHLSL += " float4 "; break;
+ case GL_FLOAT_MAT2: mVertexHLSL += " float2x2 "; break;
+ case GL_FLOAT_MAT3: mVertexHLSL += " float3x3 "; break;
+ case GL_FLOAT_MAT4: mVertexHLSL += " float4x4 "; break;
+ default: UNREACHABLE();
+ }
+
+ mVertexHLSL += decorate(attribute->name) + " : TEXCOORD" + str(semanticIndex) + ";\n";
+
+ semanticIndex += VariableRowCount(attribute->type);
+ }
+
+ mVertexHLSL += "};\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));
+
+ mVertexHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
+ }
+
+ if (mFragmentShader->mUsesFragCoord)
+ {
+ mVertexHLSL += " float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
+ }
+
+ if (mVertexShader->mUsesPointSize && sm3)
+ {
+ mVertexHLSL += " float gl_PointSize : PSIZE;\n";
+ }
+
+ mVertexHLSL += "};\n"
+ "\n"
+ "VS_OUTPUT main(VS_INPUT input)\n"
+ "{\n";
+
+ for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
+ {
+ mVertexHLSL += " " + decorate(attribute->name) + " = ";
+
+ if (VariableRowCount(attribute->type) > 1) // Matrix
+ {
+ mVertexHLSL += "transpose";
+ }
+
+ mVertexHLSL += "(input." + decorate(attribute->name) + ");\n";
+ }
+
+ mVertexHLSL += "\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 (mVertexShader->mUsesPointSize && sm3)
+ {
+ mVertexHLSL += " output.gl_PointSize = clamp(gl_PointSize, 1.0, " + str((int)ALIASED_POINT_SIZE_RANGE_MAX_SM3) + ");\n";
+ }
+
+ if (mFragmentShader->mUsesFragCoord)
+ {
+ mVertexHLSL += " output.gl_FragCoord = gl_Position;\n";
+ }
+
+ for (VaryingList::iterator varying = mVertexShader->varyings.begin(); varying != mVertexShader->varyings.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;
+ mVertexHLSL += " 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)
+ {
+ mVertexHLSL += ".";
+
+ for (int x = 0; x < 4; x++)
+ {
+ if (packing[r][x] == &*varying)
+ {
+ switch(x)
+ {
+ case 0: mVertexHLSL += "x"; break;
+ case 1: mVertexHLSL += "y"; break;
+ case 2: mVertexHLSL += "z"; break;
+ case 3: mVertexHLSL += "w"; break;
+ }
+ }
+ }
+ }
+
+ mVertexHLSL += " = " + varying->name;
+
+ if (varying->array)
+ {
+ mVertexHLSL += "[" + str(i) + "]";
+ }
+
+ if (rows > 1)
+ {
+ mVertexHLSL += "[" + str(j) + "]";
+ }
+
+ mVertexHLSL += ";\n";
+ }
+ }
+ }
+ }
+
+ mVertexHLSL += "\n"
+ " return output;\n"
+ "}\n";
+
+ mPixelHLSL += "struct PS_INPUT\n"
+ "{\n";
+
+ for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.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);
+ mPixelHLSL += " float4 v" + n + " : " + varyingSemantic + n + ";\n";
+ }
+ }
+ }
+ else UNREACHABLE();
+ }
+
+ if (mFragmentShader->mUsesFragCoord)
+ {
+ mPixelHLSL += " float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
+ }
+
+ if (mFragmentShader->mUsesPointCoord && sm3)
+ {
+ mPixelHLSL += " float2 gl_PointCoord : TEXCOORD0;\n";
+ }
+
+ if (mFragmentShader->mUsesFrontFacing)
+ {
+ mPixelHLSL += " float vFace : VFACE;\n";
+ }
+
+ mPixelHLSL += "};\n"
+ "\n"
+ "struct PS_OUTPUT\n"
+ "{\n"
+ " float4 gl_Color[1] : COLOR;\n"
+ "};\n"
+ "\n"
+ "PS_OUTPUT main(PS_INPUT input)\n"
+ "{\n";
+
+ if (mFragmentShader->mUsesFragCoord)
+ {
+ mPixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n"
+ " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_Viewport.x + dx_Viewport.z;\n"
+ " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_Viewport.y + dx_Viewport.w;\n"
+ " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_Depth.x + dx_Depth.y;\n"
+ " gl_FragCoord.w = rhw;\n";
+ }
+
+ if (mFragmentShader->mUsesPointCoord && sm3)
+ {
+ mPixelHLSL += " gl_PointCoord = float2(input.gl_PointCoord.x, 1.0 - input.gl_PointCoord.y);\n";
+ }
+
+ if (mFragmentShader->mUsesFrontFacing)
+ {
+ mPixelHLSL += " gl_FrontFacing = dx_PointsOrLines || (dx_FrontCCW ? (input.vFace >= 0.0) : (input.vFace <= 0.0));\n";
+ }
+
+ for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.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);
+ mPixelHLSL += " " + varying->name;
+
+ if (varying->array)
+ {
+ mPixelHLSL += "[" + str(i) + "]";
+ }
+
+ if (rows > 1)
+ {
+ mPixelHLSL += "[" + str(j) + "]";
+ }
+
+ mPixelHLSL += " = input.v" + n + ";\n";
+ }
+ }
+ }
+ else UNREACHABLE();
+ }
+
+ mPixelHLSL += "\n"
+ " gl_main();\n"
+ "\n"
+ " PS_OUTPUT output;\n"
+ " output.gl_Color[0] = gl_Color[0];\n"
+ "\n"
+ " return output;\n"
+ "}\n";
+
+ TRACE("\n%s", mPixelHLSL.c_str());
+ TRACE("\n%s", mVertexHLSL.c_str());
+
+ return true;
+}
+
+// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
+// compiling them into binaries, determining the attribute mappings, and collecting
+// a list of uniforms
+void Program::link()
+{
+ unlink();
+
+ if (!mFragmentShader || !mFragmentShader->isCompiled())
+ {
+ return;
+ }
+
+ if (!mVertexShader || !mVertexShader->isCompiled())
+ {
+ return;
+ }
+
+ mPixelHLSL = mFragmentShader->getHLSL();
+ mVertexHLSL = mVertexShader->getHLSL();
+
+ if (!linkVaryings())
+ {
+ return;
+ }
+
+ 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";
+
+ ID3DXBuffer *vertexBinary = compileToBinary(mVertexHLSL.c_str(), vertexProfile, &mConstantTableVS);
+ ID3DXBuffer *pixelBinary = compileToBinary(mPixelHLSL.c_str(), pixelProfile, &mConstantTablePS);
+
+ if (vertexBinary && pixelBinary)
+ {
+ IDirect3DDevice9 *device = getDevice();
+ HRESULT vertexResult = device->CreateVertexShader((DWORD*)vertexBinary->GetBufferPointer(), &mVertexExecutable);
+ HRESULT pixelResult = device->CreatePixelShader((DWORD*)pixelBinary->GetBufferPointer(), &mPixelExecutable);
+
+ if (vertexResult == D3DERR_OUTOFVIDEOMEMORY || vertexResult == E_OUTOFMEMORY || pixelResult == D3DERR_OUTOFVIDEOMEMORY || pixelResult == E_OUTOFMEMORY)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+
+ ASSERT(SUCCEEDED(vertexResult) && SUCCEEDED(pixelResult));
+
+ vertexBinary->Release();
+ pixelBinary->Release();
+ vertexBinary = NULL;
+ pixelBinary = NULL;
+
+ if (mVertexExecutable && mPixelExecutable)
+ {
+ if (!linkAttributes())
+ {
+ return;
+ }
+
+ if (!linkUniforms(mConstantTablePS))
+ {
+ return;
+ }
+
+ if (!linkUniforms(mConstantTableVS))
+ {
+ return;
+ }
+
+ // these uniforms are searched as already-decorated because gl_ and dx_
+ // are reserved prefixes, and do not receive additional decoration
+ mDepthRangeNearLocation = getUniformLocation("gl_DepthRange.near", true);
+ mDepthRangeFarLocation = getUniformLocation("gl_DepthRange.far", true);
+ mDepthRangeDiffLocation = getUniformLocation("gl_DepthRange.diff", true);
+ mDxDepthLocation = getUniformLocation("dx_Depth", true);
+ mDxViewportLocation = getUniformLocation("dx_Viewport", true);
+ mDxHalfPixelSizeLocation = getUniformLocation("dx_HalfPixelSize", true);
+ mDxFrontCCWLocation = getUniformLocation("dx_FrontCCW", true);
+ mDxPointsOrLinesLocation = getUniformLocation("dx_PointsOrLines", true);
+
+ mLinked = true; // Success
+ }
+ }
+}
+
+// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
+bool Program::linkAttributes()
+{
+ unsigned int usedLocations = 0;
+
+ // Link attributes that have a binding location
+ for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
+ {
+ int location = 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)
+ {
+ appendToInfoLog("Active attribute (%s) at location %d is too big to fit", attribute->name.c_str(), location);
+
+ return false;
+ }
+
+ for (int i = 0; i < rows; i++)
+ {
+ usedLocations |= 1 << (location + i);
+ }
+ }
+ }
+
+ // Link attributes that don't have a binding location
+ for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
+ {
+ int location = getAttributeBinding(attribute->name);
+
+ if (location == -1) // Not set by glBindAttribLocation
+ {
+ int rows = VariableRowCount(attribute->type);
+ int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
+
+ if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
+ {
+ appendToInfoLog("Too many active attributes (%s)", attribute->name.c_str());
+
+ return false; // Fail to link
+ }
+
+ mLinkedAttribute[availableIndex] = *attribute;
+ }
+ }
+
+ for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
+ {
+ int index = mVertexShader->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;
+}
+
+int Program::getAttributeBinding(const std::string &name)
+{
+ for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
+ {
+ if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
+ {
+ return location;
+ }
+ }
+
+ return -1;
+}
+
+bool Program::linkUniforms(ID3DXConstantTable *constantTable)
+{
+ D3DXCONSTANTTABLE_DESC constantTableDescription;
+ D3DXCONSTANT_DESC constantDescription;
+ UINT descriptionCount = 1;
+
+ constantTable->GetDesc(&constantTableDescription);
+
+ for (unsigned int constantIndex = 0; constantIndex < constantTableDescription.Constants; constantIndex++)
+ {
+ D3DXHANDLE constantHandle = constantTable->GetConstant(0, constantIndex);
+ constantTable->GetConstantDesc(constantHandle, &constantDescription, &descriptionCount);
+
+ if (!defineUniform(constantHandle, constantDescription))
+ {
+ 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 Program::defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT_DESC &constantDescription, std::string name)
+{
+ if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
+ {
+ unsigned int samplerIndex = constantDescription.RegisterIndex;
+
+ assert(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]));
+
+ mSamplers[samplerIndex].active = true;
+ mSamplers[samplerIndex].type = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? SAMPLER_CUBE : SAMPLER_2D;
+ mSamplers[samplerIndex].logicalTextureUnit = 0;
+ mSamplers[samplerIndex].dirty = true;
+ }
+
+ switch(constantDescription.Class)
+ {
+ case D3DXPC_STRUCT:
+ {
+ for (unsigned int field = 0; field < constantDescription.StructMembers; field++)
+ {
+ D3DXHANDLE fieldHandle = mConstantTablePS->GetConstant(constantHandle, field);
+
+ D3DXCONSTANT_DESC fieldDescription;
+ UINT descriptionCount = 1;
+
+ mConstantTablePS->GetConstantDesc(fieldHandle, &fieldDescription, &descriptionCount);
+
+ if (!defineUniform(fieldHandle, fieldDescription, name + constantDescription.Name + "."))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ case D3DXPC_SCALAR:
+ case D3DXPC_VECTOR:
+ case D3DXPC_MATRIX_COLUMNS:
+ case D3DXPC_OBJECT:
+ return defineUniform(constantDescription, name + constantDescription.Name);
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+bool Program::defineUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name)
+{
+ Uniform *uniform = createUniform(constantDescription, name);
+
+ if(!uniform)
+ {
+ return false;
+ }
+
+ // Check if already defined
+ GLint location = getUniformLocation(name.c_str(), true);
+ GLenum type = uniform->type;
+
+ if (location >= 0)
+ {
+ delete uniform;
+
+ if (mUniforms[mUniformIndex[location].index]->type != type)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ 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 *Program::createUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name)
+{
+ if (constantDescription.Rows == 1) // Vectors and scalars
+ {
+ switch (constantDescription.Type)
+ {
+ case D3DXPT_SAMPLER2D:
+ case D3DXPT_SAMPLERCUBE:
+ switch (constantDescription.Columns)
+ {
+ case 1: return new Uniform(GL_INT, name, constantDescription.Elements);
+ default: UNREACHABLE();
+ }
+ break;
+ case D3DXPT_BOOL:
+ switch (constantDescription.Columns)
+ {
+ case 1: return new Uniform(GL_BOOL, name, constantDescription.Elements);
+ case 2: return new Uniform(GL_BOOL_VEC2, name, constantDescription.Elements);
+ case 3: return new Uniform(GL_BOOL_VEC3, name, constantDescription.Elements);
+ case 4: return new Uniform(GL_BOOL_VEC4, name, constantDescription.Elements);
+ default: UNREACHABLE();
+ }
+ break;
+ case D3DXPT_INT:
+ switch (constantDescription.Columns)
+ {
+ case 1: return new Uniform(GL_INT, name, constantDescription.Elements);
+ case 2: return new Uniform(GL_INT_VEC2, name, constantDescription.Elements);
+ case 3: return new Uniform(GL_INT_VEC3, name, constantDescription.Elements);
+ case 4: return new Uniform(GL_INT_VEC4, name, constantDescription.Elements);
+ default: UNREACHABLE();
+ }
+ break;
+ case D3DXPT_FLOAT:
+ switch (constantDescription.Columns)
+ {
+ case 1: return new Uniform(GL_FLOAT, name, constantDescription.Elements);
+ case 2: return new Uniform(GL_FLOAT_VEC2, name, constantDescription.Elements);
+ case 3: return new Uniform(GL_FLOAT_VEC3, name, constantDescription.Elements);
+ case 4: return new Uniform(GL_FLOAT_VEC4, name, constantDescription.Elements);
+ default: UNREACHABLE();
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ else if (constantDescription.Rows == constantDescription.Columns) // Square matrices
+ {
+ switch (constantDescription.Type)
+ {
+ case D3DXPT_FLOAT:
+ switch (constantDescription.Rows)
+ {
+ case 2: return new Uniform(GL_FLOAT_MAT2, name, constantDescription.Elements);
+ case 3: return new Uniform(GL_FLOAT_MAT3, name, constantDescription.Elements);
+ case 4: return new Uniform(GL_FLOAT_MAT4, name, constantDescription.Elements);
+ default: UNREACHABLE();
+ }
+ break;
+ default: UNREACHABLE();
+ }
+ }
+ else UNREACHABLE();
+
+ return 0;
+}
+
+// This method needs to match OutputHLSL::decorate
+std::string Program::decorate(const std::string &string)
+{
+ if (string.substr(0, 3) != "gl_" && string.substr(0, 3) != "dx_")
+ {
+ return "_" + string;
+ }
+ else
+ {
+ return string;
+ }
+}
+
+std::string Program::undecorate(const std::string &string)
+{
+ if (string.substr(0, 1) == "_")
+ {
+ return string.substr(1);
+ }
+ else
+ {
+ return string;
+ }
+}
+
+bool Program::applyUniform1bv(GLint location, GLsizei count, const GLboolean *v)
+{
+ BOOL *vector = new BOOL[count];
+ for (int i = 0; i < count; i++)
+ {
+ if (v[i] == GL_FALSE)
+ vector[i] = 0;
+ else
+ vector[i] = 1;
+ }
+
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ D3DXHANDLE constantPS;
+ D3DXHANDLE constantVS;
+ getConstantHandles(targetUniform, &constantPS, &constantVS);
+
+ IDirect3DDevice9 *device = getDevice();
+
+ if (constantPS)
+ {
+ mConstantTablePS->SetBoolArray(device, constantPS, vector, count);
+ }
+
+ if (constantVS)
+ {
+ mConstantTableVS->SetBoolArray(device, constantVS, vector, count);
+ }
+
+ delete [] vector;
+
+ return true;
+}
+
+bool Program::applyUniform2bv(GLint location, GLsizei count, const GLboolean *v)
+{
+ D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
+ (v[1] == GL_FALSE ? 0.0f : 1.0f), 0, 0);
+
+ v += 2;
+ }
+
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ D3DXHANDLE constantPS;
+ D3DXHANDLE constantVS;
+ getConstantHandles(targetUniform, &constantPS, &constantVS);
+ IDirect3DDevice9 *device = getDevice();
+
+ if (constantPS)
+ {
+ mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
+ }
+
+ if (constantVS)
+ {
+ mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
+ }
+
+ delete[] vector;
+
+ return true;
+}
+
+bool Program::applyUniform3bv(GLint location, GLsizei count, const GLboolean *v)
+{
+ D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
+ (v[1] == GL_FALSE ? 0.0f : 1.0f),
+ (v[2] == GL_FALSE ? 0.0f : 1.0f), 0);
+
+ v += 3;
+ }
+
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ D3DXHANDLE constantPS;
+ D3DXHANDLE constantVS;
+ getConstantHandles(targetUniform, &constantPS, &constantVS);
+ IDirect3DDevice9 *device = getDevice();
+
+ if (constantPS)
+ {
+ mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
+ }
+
+ if (constantVS)
+ {
+ mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
+ }
+
+ delete[] vector;
+
+ return true;
+}
+
+bool Program::applyUniform4bv(GLint location, GLsizei count, const GLboolean *v)
+{
+ D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
+ (v[1] == GL_FALSE ? 0.0f : 1.0f),
+ (v[2] == GL_FALSE ? 0.0f : 1.0f),
+ (v[3] == GL_FALSE ? 0.0f : 1.0f));
+
+ v += 3;
+ }
+
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ D3DXHANDLE constantPS;
+ D3DXHANDLE constantVS;
+ getConstantHandles(targetUniform, &constantPS, &constantVS);
+ IDirect3DDevice9 *device = getDevice();
+
+ if (constantPS)
+ {
+ mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
+ }
+
+ if (constantVS)
+ {
+ mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
+ }
+
+ delete [] vector;
+
+ return true;
+}
+
+bool Program::applyUniform1fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ D3DXHANDLE constantPS;
+ D3DXHANDLE constantVS;
+ getConstantHandles(targetUniform, &constantPS, &constantVS);
+ IDirect3DDevice9 *device = getDevice();
+
+ if (constantPS)
+ {
+ mConstantTablePS->SetFloatArray(device, constantPS, v, count);
+ }
+
+ if (constantVS)
+ {
+ mConstantTableVS->SetFloatArray(device, constantVS, v, count);
+ }
+
+ return true;
+}
+
+bool Program::applyUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ vector[i] = D3DXVECTOR4(v[0], v[1], 0, 0);
+
+ v += 2;
+ }
+
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ D3DXHANDLE constantPS;
+ D3DXHANDLE constantVS;
+ getConstantHandles(targetUniform, &constantPS, &constantVS);
+ IDirect3DDevice9 *device = getDevice();
+
+ if (constantPS)
+ {
+ mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
+ }
+
+ if (constantVS)
+ {
+ mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
+ }
+
+ delete[] vector;
+
+ return true;
+}
+
+bool Program::applyUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ vector[i] = D3DXVECTOR4(v[0], v[1], v[2], 0);
+
+ v += 3;
+ }
+
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ D3DXHANDLE constantPS;
+ D3DXHANDLE constantVS;
+ getConstantHandles(targetUniform, &constantPS, &constantVS);
+ IDirect3DDevice9 *device = getDevice();
+
+ if (constantPS)
+ {
+ mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
+ }
+
+ if (constantVS)
+ {
+ mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
+ }
+
+ delete[] vector;
+
+ return true;
+}
+
+bool Program::applyUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ D3DXHANDLE constantPS;
+ D3DXHANDLE constantVS;
+ getConstantHandles(targetUniform, &constantPS, &constantVS);
+ IDirect3DDevice9 *device = getDevice();
+
+ if (constantPS)
+ {
+ mConstantTablePS->SetVectorArray(device, constantPS, (D3DXVECTOR4*)v, count);
+ }
+
+ if (constantVS)
+ {
+ mConstantTableVS->SetVectorArray(device, constantVS, (D3DXVECTOR4*)v, count);
+ }
+
+ return true;
+}
+
+bool Program::applyUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
+{
+ D3DXMATRIX *matrix = new D3DXMATRIX[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ matrix[i] = D3DXMATRIX(value[0], value[2], 0, 0,
+ value[1], value[3], 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1);
+
+ value += 4;
+ }
+
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ D3DXHANDLE constantPS;
+ D3DXHANDLE constantVS;
+ getConstantHandles(targetUniform, &constantPS, &constantVS);
+ IDirect3DDevice9 *device = getDevice();
+
+ if (constantPS)
+ {
+ mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
+ }
+
+ if (constantVS)
+ {
+ mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
+ }
+
+ delete[] matrix;
+
+ return true;
+}
+
+bool Program::applyUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
+{
+ D3DXMATRIX *matrix = new D3DXMATRIX[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ matrix[i] = D3DXMATRIX(value[0], value[3], value[6], 0,
+ value[1], value[4], value[7], 0,
+ value[2], value[5], value[8], 0,
+ 0, 0, 0, 1);
+
+ value += 9;
+ }
+
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ D3DXHANDLE constantPS;
+ D3DXHANDLE constantVS;
+ getConstantHandles(targetUniform, &constantPS, &constantVS);
+ IDirect3DDevice9 *device = getDevice();
+
+ if (constantPS)
+ {
+ mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
+ }
+
+ if (constantVS)
+ {
+ mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
+ }
+
+ delete[] matrix;
+
+ return true;
+}
+
+bool Program::applyUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
+{
+ D3DXMATRIX *matrix = new D3DXMATRIX[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ matrix[i] = D3DXMATRIX(value[0], value[4], value[8], value[12],
+ value[1], value[5], value[9], value[13],
+ value[2], value[6], value[10], value[14],
+ value[3], value[7], value[11], value[15]);
+
+ value += 16;
+ }
+
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ D3DXHANDLE constantPS;
+ D3DXHANDLE constantVS;
+ getConstantHandles(targetUniform, &constantPS, &constantVS);
+ IDirect3DDevice9 *device = getDevice();
+
+ if (constantPS)
+ {
+ mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
+ }
+
+ if (constantVS)
+ {
+ mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
+ }
+
+ delete[] matrix;
+
+ return true;
+}
+
+bool Program::applyUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ D3DXHANDLE constantPS;
+ D3DXHANDLE constantVS;
+ getConstantHandles(targetUniform, &constantPS, &constantVS);
+ IDirect3DDevice9 *device = getDevice();
+
+ if (constantPS)
+ {
+ D3DXCONSTANT_DESC constantDescription;
+ UINT descriptionCount = 1;
+ HRESULT result = mConstantTablePS->GetConstantDesc(constantPS, &constantDescription, &descriptionCount);
+
+ if (FAILED(result))
+ {
+ return false;
+ }
+
+ if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
+ {
+ unsigned int firstIndex = mConstantTablePS->GetSamplerIndex(constantPS);
+
+ for (unsigned int samplerIndex = firstIndex; samplerIndex < firstIndex + count; samplerIndex++)
+ {
+ GLint mappedSampler = v[0];
+
+ if (samplerIndex >= 0 && samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
+ {
+ ASSERT(mSamplers[samplerIndex].active);
+ mSamplers[samplerIndex].logicalTextureUnit = mappedSampler;
+ mSamplers[samplerIndex].dirty = true;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ if (constantPS)
+ {
+ mConstantTablePS->SetIntArray(device, constantPS, v, count);
+ }
+
+ if (constantVS)
+ {
+ mConstantTableVS->SetIntArray(device, constantVS, v, count);
+ }
+
+ return true;
+}
+
+bool Program::applyUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+ D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], 0, 0);
+
+ v += 2;
+ }
+
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ D3DXHANDLE constantPS;
+ D3DXHANDLE constantVS;
+ getConstantHandles(targetUniform, &constantPS, &constantVS);
+ IDirect3DDevice9 *device = getDevice();
+
+ if (constantPS)
+ {
+ mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
+ }
+
+ if (constantVS)
+ {
+ mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
+ }
+
+ delete[] vector;
+
+ return true;
+}
+
+bool Program::applyUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+ D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], (float)v[2], 0);
+
+ v += 3;
+ }
+
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ D3DXHANDLE constantPS;
+ D3DXHANDLE constantVS;
+ getConstantHandles(targetUniform, &constantPS, &constantVS);
+ IDirect3DDevice9 *device = getDevice();
+
+ if (constantPS)
+ {
+ mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
+ }
+
+ if (constantVS)
+ {
+ mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
+ }
+
+ delete[] vector;
+
+ return true;
+}
+
+bool Program::applyUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+ D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], (float)v[2], (float)v[3]);
+
+ v += 4;
+ }
+
+ Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ D3DXHANDLE constantPS;
+ D3DXHANDLE constantVS;
+ getConstantHandles(targetUniform, &constantPS, &constantVS);
+ IDirect3DDevice9 *device = getDevice();
+
+ if (constantPS)
+ {
+ mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
+ }
+
+ if (constantVS)
+ {
+ mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
+ }
+
+ delete [] vector;
+
+ return true;
+}
+
+void Program::appendToInfoLog(const char *format, ...)
+{
+ if (!format)
+ {
+ return;
+ }
+
+ char info[1024];
+
+ va_list vararg;
+ va_start(vararg, format);
+ vsnprintf(info, sizeof(info), format, vararg);
+ va_end(vararg);
+
+ size_t infoLength = strlen(info);
+
+ if (!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 Program::resetInfoLog()
+{
+ if (mInfoLog)
+ {
+ delete [] mInfoLog;
+ }
+}
+
+// Returns the program object to an unlinked state, after detaching a shader, before re-linking, or at destruction
+void Program::unlink(bool destroy)
+{
+ if (destroy) // Object being destructed
+ {
+ if (mFragmentShader)
+ {
+ mFragmentShader->release();
+ mFragmentShader = NULL;
+ }
+
+ if (mVertexShader)
+ {
+ mVertexShader->release();
+ mVertexShader = NULL;
+ }
+ }
+
+ if (mPixelExecutable)
+ {
+ mPixelExecutable->Release();
+ mPixelExecutable = NULL;
+ }
+
+ if (mVertexExecutable)
+ {
+ mVertexExecutable->Release();
+ mVertexExecutable = NULL;
+ }
+
+ if (mConstantTablePS)
+ {
+ mConstantTablePS->Release();
+ mConstantTablePS = NULL;
+ }
+
+ if (mConstantTableVS)
+ {
+ mConstantTableVS->Release();
+ mConstantTableVS = NULL;
+ }
+
+ for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
+ {
+ mLinkedAttribute[index].name.clear();
+ mSemanticIndex[index] = -1;
+ }
+
+ for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
+ {
+ mSamplers[index].active = false;
+ mSamplers[index].dirty = true;
+ }
+
+ while (!mUniforms.empty())
+ {
+ delete mUniforms.back();
+ mUniforms.pop_back();
+ }
+
+ mDepthRangeDiffLocation = -1;
+ mDepthRangeNearLocation = -1;
+ mDepthRangeFarLocation = -1;
+ mDxDepthLocation = -1;
+ mDxViewportLocation = -1;
+ mDxHalfPixelSizeLocation = -1;
+ mDxFrontCCWLocation = -1;
+ mDxPointsOrLinesLocation = -1;
+
+ mUniformIndex.clear();
+
+ mPixelHLSL.clear();
+ mVertexHLSL.clear();
+
+ delete[] mInfoLog;
+ mInfoLog = NULL;
+
+ mLinked = false;
+}
+
+bool Program::isLinked()
+{
+ return mLinked;
+}
+
+bool Program::isValidated() const
+{
+ return mValidated;
+}
+
+void Program::release()
+{
+ mRefCount--;
+
+ if (mRefCount == 0 && mDeleteStatus)
+ {
+ mResourceManager->deleteProgram(mHandle);
+ }
+}
+
+void Program::addRef()
+{
+ mRefCount++;
+}
+
+unsigned int Program::getRefCount() const
+{
+ return mRefCount;
+}
+
+unsigned int Program::getSerial() const
+{
+ return mSerial;
+}
+
+unsigned int Program::issueSerial()
+{
+ return mCurrentSerial++;
+}
+
+int Program::getInfoLogLength() const
+{
+ if (!mInfoLog)
+ {
+ return 0;
+ }
+ else
+ {
+ return strlen(mInfoLog) + 1;
+ }
+}
+
+void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
+{
+ int index = 0;
+
+ if (mInfoLog)
+ {
+ while (index < bufSize - 1 && index < (int)strlen(mInfoLog))
+ {
+ infoLog[index] = mInfoLog[index];
+ index++;
+ }
+ }
+
+ if (bufSize)
+ {
+ infoLog[index] = '\0';
+ }
+
+ if (length)
+ {
+ *length = index;
+ }
+}
+
+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)
+{
+ unsigned int attribute = 0;
+ for (unsigned int i = 0; i < index; i++)
+ {
+ do
+ {
+ attribute++;
+
+ ASSERT(attribute < MAX_VERTEX_ATTRIBS); // index must be smaller than getActiveAttributeCount()
+ }
+ while (mLinkedAttribute[attribute].name.empty());
+ }
+
+ 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 Program::getActiveAttributeCount()
+{
+ int count = 0;
+
+ for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+ {
+ if (!mLinkedAttribute[attributeIndex].name.empty())
+ {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+GLint Program::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 Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+{
+ unsigned int uniform = 0;
+ for (unsigned int i = 0; i < index; i++)
+ {
+ do
+ {
+ uniform++;
+
+ ASSERT(uniform < mUniforms.size()); // index must be smaller than getActiveUniformCount()
+ }
+ while (mUniforms[uniform]->name.substr(0, 3) == "dx_");
+ }
+
+ if (bufsize > 0)
+ {
+ std::string string = undecorate(mUniforms[uniform]->name);
+
+ if (mUniforms[uniform]->arraySize != 1)
+ {
+ 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 Program::getActiveUniformCount()
+{
+ int count = 0;
+
+ unsigned int numUniforms = mUniforms.size();
+ for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
+ {
+ if (mUniforms[uniformIndex]->name.substr(0, 3) != "dx_")
+ {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+GLint Program::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.substr(0, 3) != "dx_")
+ {
+ maxLength = std::max((int)(undecorate(mUniforms[uniformIndex]->name).length() + 1), maxLength);
+ }
+ }
+
+ return maxLength;
+}
+
+void Program::flagForDeletion()
+{
+ mDeleteStatus = true;
+}
+
+bool Program::isFlaggedForDeletion() const
+{
+ return mDeleteStatus;
+}
+
+void Program::validate()
+{
+ resetInfoLog();
+
+ if (!isLinked())
+ {
+ appendToInfoLog("Program has not been successfully linked.");
+ mValidated = false;
+ }
+ else
+ {
+ applyUniforms();
+ if (!validateSamplers())
+ {
+ appendToInfoLog("Samplers of conflicting types refer to the same texture image unit.");
+ mValidated = false;
+ }
+ else
+ {
+ mValidated = true;
+ }
+ }
+}
+
+bool Program::validateSamplers() const
+{
+ // 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.
+ std::map<int, SamplerType> samplerMap;
+ for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
+ {
+ if (mSamplers[i].active)
+ {
+ if (samplerMap.find(mSamplers[i].logicalTextureUnit) != samplerMap.end())
+ {
+ if (mSamplers[i].type != samplerMap[mSamplers[i].logicalTextureUnit])
+ return false;
+ }
+ else
+ {
+ samplerMap[mSamplers[i].logicalTextureUnit] = mSamplers[i].type;
+ }
+ }
+ }
+
+ return true;
+}
+
+void Program::getConstantHandles(Uniform *targetUniform, D3DXHANDLE *constantPS, D3DXHANDLE *constantVS)
+{
+ if (!targetUniform->handlesSet)
+ {
+ targetUniform->psHandle = mConstantTablePS->GetConstantByName(0, targetUniform->name.c_str());
+ targetUniform->vsHandle = mConstantTableVS->GetConstantByName(0, targetUniform->name.c_str());
+ targetUniform->handlesSet = true;
+ }
+
+ *constantPS = targetUniform->psHandle;
+ *constantVS = targetUniform->vsHandle;
+}
+
+GLint Program::getDepthRangeDiffLocation() const
+{
+ return mDepthRangeDiffLocation;
+}
+
+GLint Program::getDepthRangeNearLocation() const
+{
+ return mDepthRangeNearLocation;
+}
+
+GLint Program::getDepthRangeFarLocation() const
+{
+ return mDepthRangeFarLocation;
+}
+
+GLint Program::getDxDepthLocation() const
+{
+ return mDxDepthLocation;
+}
+
+GLint Program::getDxViewportLocation() const
+{
+ return mDxViewportLocation;
+}
+
+GLint Program::getDxHalfPixelSizeLocation() const
+{
+ return mDxHalfPixelSizeLocation;
+}
+
+GLint Program::getDxFrontCCWLocation() const
+{
+ return mDxFrontCCWLocation;
+}
+
+GLint Program::getDxPointsOrLinesLocation() const
+{
+ return mDxPointsOrLinesLocation;
+}
+
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Program.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Program.h
new file mode 100644
index 0000000..3021b7a
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Program.h
@@ -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.
+//
+
+// 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 <d3dx9.h>
+#include <string>
+#include <vector>
+#include <set>
+
+#include "libGLESv2/Shader.h"
+#include "libGLESv2/Context.h"
+
+namespace gl
+{
+class ResourceManager;
+class FragmentShader;
+class VertexShader;
+
+// Helper struct representing a single shader uniform
+struct Uniform
+{
+ Uniform(GLenum type, const std::string &name, unsigned int arraySize);
+
+ ~Uniform();
+
+ const GLenum type;
+ const std::string name;
+ const unsigned int arraySize;
+
+ unsigned char *data;
+ bool dirty;
+
+ D3DXHANDLE vsHandle;
+ D3DXHANDLE psHandle;
+ bool handlesSet;
+};
+
+// Struct used for correlating uniforms/elements of uniform arrays to handles
+struct UniformLocation
+{
+ UniformLocation(const std::string &name, unsigned int element, unsigned int index);
+
+ std::string name;
+ unsigned int element;
+ unsigned int index;
+};
+
+class Program
+{
+ public:
+ Program(ResourceManager *manager, GLuint handle);
+
+ ~Program();
+
+ bool attachShader(Shader *shader);
+ bool detachShader(Shader *shader);
+ int getAttachedShadersCount() const;
+
+ IDirect3DPixelShader9 *getPixelShader();
+ IDirect3DVertexShader9 *getVertexShader();
+
+ void bindAttributeLocation(GLuint index, const char *name);
+ GLuint getAttributeLocation(const char *name);
+ int getSemanticIndex(int attributeIndex);
+
+ void dirtyAllSamplers();
+
+ GLint getSamplerMapping(unsigned int samplerIndex);
+ SamplerType getSamplerType(unsigned int samplerIndex);
+ bool isSamplerDirty(unsigned int samplerIndex) const;
+ void setSamplerDirty(unsigned int samplerIndex, bool dirty);
+
+ GLint getUniformLocation(const char *name, bool decorated);
+ 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, GLfloat *params);
+ bool getUniformiv(GLint location, GLint *params);
+
+ GLint getDepthRangeDiffLocation() const;
+ GLint getDepthRangeNearLocation() const;
+ GLint getDepthRangeFarLocation() const;
+ GLint getDxDepthLocation() const;
+ GLint getDxViewportLocation() const;
+ GLint getDxHalfPixelSizeLocation() const;
+ GLint getDxFrontCCWLocation() const;
+ GLint getDxPointsOrLinesLocation() const;
+
+ void dirtyAllUniforms();
+ void applyUniforms();
+
+ void link();
+ bool isLinked();
+ int getInfoLogLength() const;
+ void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
+ void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
+
+ void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+ GLint getActiveAttributeCount();
+ GLint getActiveAttributeMaxLength();
+
+ void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+ GLint getActiveUniformCount();
+ GLint getActiveUniformMaxLength();
+
+ void addRef();
+ void release();
+ unsigned int getRefCount() const;
+ void flagForDeletion();
+ bool isFlaggedForDeletion() const;
+
+ void validate();
+ bool validateSamplers() const;
+ bool isValidated() const;
+
+ unsigned int getSerial() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Program);
+
+ ID3DXBuffer *compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable);
+ void unlink(bool destroy = false);
+
+ int packVaryings(const Varying *packing[][4]);
+ bool linkVaryings();
+
+ bool linkAttributes();
+ int getAttributeBinding(const std::string &name);
+
+ bool linkUniforms(ID3DXConstantTable *constantTable);
+ bool defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT_DESC &constantDescription, std::string name = "");
+ bool defineUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name);
+ Uniform *createUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name);
+ bool applyUniform1bv(GLint location, GLsizei count, const GLboolean *v);
+ bool applyUniform2bv(GLint location, GLsizei count, const GLboolean *v);
+ bool applyUniform3bv(GLint location, GLsizei count, const GLboolean *v);
+ bool applyUniform4bv(GLint location, GLsizei count, const GLboolean *v);
+ bool applyUniform1fv(GLint location, GLsizei count, const GLfloat *v);
+ bool applyUniform2fv(GLint location, GLsizei count, const GLfloat *v);
+ bool applyUniform3fv(GLint location, GLsizei count, const GLfloat *v);
+ bool applyUniform4fv(GLint location, GLsizei count, const GLfloat *v);
+ bool applyUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value);
+ bool applyUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value);
+ bool applyUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value);
+ bool applyUniform1iv(GLint location, GLsizei count, const GLint *v);
+ bool applyUniform2iv(GLint location, GLsizei count, const GLint *v);
+ bool applyUniform3iv(GLint location, GLsizei count, const GLint *v);
+ bool applyUniform4iv(GLint location, GLsizei count, const GLint *v);
+
+ void getConstantHandles(Uniform *targetUniform, D3DXHANDLE *constantPS, D3DXHANDLE *constantVS);
+
+ void appendToInfoLog(const char *info, ...);
+ void resetInfoLog();
+
+ static std::string decorate(const std::string &string); // Prepend an underscore
+ static std::string undecorate(const std::string &string); // Remove leading underscore
+
+ static unsigned int issueSerial();
+
+ FragmentShader *mFragmentShader;
+ VertexShader *mVertexShader;
+
+ std::string mPixelHLSL;
+ std::string mVertexHLSL;
+
+ IDirect3DPixelShader9 *mPixelExecutable;
+ IDirect3DVertexShader9 *mVertexExecutable;
+ ID3DXConstantTable *mConstantTablePS;
+ ID3DXConstantTable *mConstantTableVS;
+
+ std::set<std::string> mAttributeBinding[MAX_VERTEX_ATTRIBS];
+ Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS];
+ int mSemanticIndex[MAX_VERTEX_ATTRIBS];
+
+ struct Sampler
+ {
+ bool active;
+ GLint logicalTextureUnit;
+ SamplerType type;
+ bool dirty;
+ };
+
+ Sampler mSamplers[MAX_TEXTURE_IMAGE_UNITS];
+
+ typedef std::vector<Uniform*> UniformArray;
+ UniformArray mUniforms;
+ typedef std::vector<UniformLocation> UniformIndex;
+ UniformIndex mUniformIndex;
+
+ GLint mDepthRangeDiffLocation;
+ GLint mDepthRangeNearLocation;
+ GLint mDepthRangeFarLocation;
+ GLint mDxDepthLocation;
+ GLint mDxViewportLocation;
+ GLint mDxHalfPixelSizeLocation;
+ GLint mDxFrontCCWLocation;
+ GLint mDxPointsOrLinesLocation;
+
+ bool mLinked;
+ bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use
+ char *mInfoLog;
+ bool mValidated;
+
+ unsigned int mRefCount;
+
+ unsigned int mSerial;
+
+ static unsigned int mCurrentSerial;
+
+ ResourceManager *mResourceManager;
+ const GLuint mHandle;
+};
+}
+
+#endif // LIBGLESV2_PROGRAM_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/RefCountObject.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/RefCountObject.cpp
new file mode 100644
index 0000000..e3fd36e
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/RefCountObject.cpp
@@ -0,0 +1,51 @@
+//
+// 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"
+
+namespace gl
+{
+
+RefCountObject::RefCountObject(GLuint id)
+{
+ mId = id;
+ mRefCount = 0;
+}
+
+RefCountObject::~RefCountObject()
+{
+}
+
+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/Source/ThirdParty/ANGLE/src/libGLESv2/RefCountObject.h b/Source/ThirdParty/ANGLE/src/libGLESv2/RefCountObject.h
new file mode 100644
index 0000000..a149350
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/RefCountObject.h
@@ -0,0 +1,70 @@
+//
+// 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 LIBGLESV2_REFCOUNTOBJECT_H_
+#define LIBGLESV2_REFCOUNTOBJECT_H_
+
+#include <cstddef>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include "common/debug.h"
+
+namespace gl
+{
+
+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 // LIBGLESV2_REFCOUNTOBJECT_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.cpp
new file mode 100644
index 0000000..0eb4637
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.cpp
@@ -0,0 +1,484 @@
+//
+// 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/utilities.h"
+
+namespace gl
+{
+unsigned int RenderbufferStorage::mCurrentSerial = 1;
+
+Renderbuffer::Renderbuffer(GLuint id, RenderbufferStorage *storage) : RefCountObject(id)
+{
+ ASSERT(storage != NULL);
+ mStorage = storage;
+}
+
+Renderbuffer::~Renderbuffer()
+{
+ delete mStorage;
+}
+
+bool Renderbuffer::isColorbuffer() const
+{
+ return mStorage->isColorbuffer();
+}
+
+bool Renderbuffer::isDepthbuffer() const
+{
+ return mStorage->isDepthbuffer();
+}
+
+bool Renderbuffer::isStencilbuffer() const
+{
+ return mStorage->isStencilbuffer();
+}
+
+IDirect3DSurface9 *Renderbuffer::getRenderTarget()
+{
+ return mStorage->getRenderTarget();
+}
+
+IDirect3DSurface9 *Renderbuffer::getDepthStencil()
+{
+ return mStorage->getDepthStencil();
+}
+
+int Renderbuffer::getWidth() const
+{
+ return mStorage->getWidth();
+}
+
+int Renderbuffer::getHeight() const
+{
+ return mStorage->getHeight();
+}
+
+GLenum Renderbuffer::getFormat() const
+{
+ return mStorage->getFormat();
+}
+
+D3DFORMAT Renderbuffer::getD3DFormat() const
+{
+ return mStorage->getD3DFormat();
+}
+
+unsigned int Renderbuffer::getSerial() const
+{
+ return mStorage->getSerial();
+}
+
+void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
+{
+ ASSERT(newStorage != NULL);
+
+ delete mStorage;
+ mStorage = newStorage;
+}
+
+RenderbufferStorage::RenderbufferStorage()
+{
+ mSerial = issueSerial();
+}
+
+RenderbufferStorage::~RenderbufferStorage()
+{
+}
+
+bool RenderbufferStorage::isColorbuffer() const
+{
+ return false;
+}
+
+bool RenderbufferStorage::isDepthbuffer() const
+{
+ return false;
+}
+
+bool RenderbufferStorage::isStencilbuffer() const
+{
+ return false;
+}
+
+IDirect3DSurface9 *RenderbufferStorage::getRenderTarget()
+{
+ return NULL;
+}
+
+IDirect3DSurface9 *RenderbufferStorage::getDepthStencil()
+{
+ return NULL;
+}
+
+int RenderbufferStorage::getWidth() const
+{
+ return mWidth;
+}
+
+int RenderbufferStorage::getHeight() const
+{
+ return mHeight;
+}
+
+void RenderbufferStorage::setSize(int width, int height)
+{
+ mWidth = width;
+ mHeight = height;
+}
+
+GLenum RenderbufferStorage::getFormat() const
+{
+ return mFormat;
+}
+
+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++;
+}
+
+Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget)
+{
+ if (renderTarget)
+ {
+ renderTarget->AddRef();
+
+ D3DSURFACE_DESC description;
+ renderTarget->GetDesc(&description);
+
+ setSize(description.Width, description.Height);
+ mD3DFormat = description.Format;
+ mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType);
+ }
+ else
+ {
+ mD3DFormat = D3DFMT_UNKNOWN;
+ mSamples = 0;
+ }
+}
+
+Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples)
+{
+ IDirect3DDevice9 *device = getDevice();
+
+ mRenderTarget = NULL;
+ 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));
+ }
+
+ if (mRenderTarget)
+ {
+ setSize(width, height);
+ mFormat = format;
+ mD3DFormat = requestedFormat;
+ mSamples = supportedSamples;
+ }
+ else
+ {
+ setSize(0, 0);
+ mFormat = GL_RGBA4;
+ mD3DFormat = D3DFMT_UNKNOWN;
+ mSamples = 0;
+ }
+}
+
+Colorbuffer::~Colorbuffer()
+{
+ if (mRenderTarget)
+ {
+ mRenderTarget->Release();
+ }
+}
+
+bool Colorbuffer::isColorbuffer() const
+{
+ return true;
+}
+
+GLuint Colorbuffer::getRedSize() const
+{
+ if (mRenderTarget)
+ {
+ D3DSURFACE_DESC description;
+ mRenderTarget->GetDesc(&description);
+
+ return es2dx::GetRedSize(description.Format);
+ }
+
+ return 0;
+}
+
+GLuint Colorbuffer::getGreenSize() const
+{
+ if (mRenderTarget)
+ {
+ D3DSURFACE_DESC description;
+ mRenderTarget->GetDesc(&description);
+
+ return es2dx::GetGreenSize(description.Format);
+ }
+
+ return 0;
+}
+
+GLuint Colorbuffer::getBlueSize() const
+{
+ if (mRenderTarget)
+ {
+ D3DSURFACE_DESC description;
+ mRenderTarget->GetDesc(&description);
+
+ return es2dx::GetBlueSize(description.Format);
+ }
+
+ return 0;
+}
+
+GLuint Colorbuffer::getAlphaSize() const
+{
+ if (mRenderTarget)
+ {
+ D3DSURFACE_DESC description;
+ mRenderTarget->GetDesc(&description);
+
+ return es2dx::GetAlphaSize(description.Format);
+ }
+
+ return 0;
+}
+
+IDirect3DSurface9 *Colorbuffer::getRenderTarget()
+{
+ return mRenderTarget;
+}
+
+DepthStencilbuffer::DepthStencilbuffer(IDirect3DSurface9 *depthStencil) : mDepthStencil(depthStencil)
+{
+ if (depthStencil)
+ {
+ depthStencil->AddRef();
+
+ D3DSURFACE_DESC description;
+ depthStencil->GetDesc(&description);
+
+ setSize(description.Width, description.Height);
+ mFormat = (description.Format == D3DFMT_D16 ? GL_DEPTH_COMPONENT16 : GL_DEPTH24_STENCIL8_OES);
+ mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType);
+ mD3DFormat = description.Format;
+ }
+ else
+ {
+ mD3DFormat = D3DFMT_UNKNOWN;
+ mSamples = 0;
+ }
+}
+
+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;
+ }
+
+ 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));
+
+ if (mDepthStencil)
+ {
+ setSize(width, height);
+ mFormat = GL_DEPTH24_STENCIL8_OES;
+ mD3DFormat = D3DFMT_D24S8;
+ mSamples = supportedSamples;
+ }
+ else
+ {
+ setSize(0, 0);
+ mFormat = GL_RGBA4; //default format
+ mD3DFormat = D3DFMT_UNKNOWN;
+ mSamples = 0;
+ }
+}
+
+DepthStencilbuffer::~DepthStencilbuffer()
+{
+ if (mDepthStencil)
+ {
+ mDepthStencil->Release();
+ }
+}
+
+bool DepthStencilbuffer::isDepthbuffer() const
+{
+ return true;
+}
+
+bool DepthStencilbuffer::isStencilbuffer() const
+{
+ return true;
+}
+
+GLuint DepthStencilbuffer::getDepthSize() const
+{
+ if (mDepthStencil)
+ {
+ D3DSURFACE_DESC description;
+ mDepthStencil->GetDesc(&description);
+
+ return es2dx::GetDepthSize(description.Format);
+ }
+
+ return 0;
+}
+
+GLuint DepthStencilbuffer::getStencilSize() const
+{
+ if (mDepthStencil)
+ {
+ D3DSURFACE_DESC description;
+ mDepthStencil->GetDesc(&description);
+
+ return es2dx::GetStencilSize(description.Format);
+ }
+
+ return 0;
+}
+
+IDirect3DSurface9 *DepthStencilbuffer::getDepthStencil()
+{
+ return mDepthStencil;
+}
+
+Depthbuffer::Depthbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil)
+{
+ if (depthStencil)
+ {
+ mFormat = 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 (getDepthStencil())
+ {
+ mFormat = 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()
+{
+}
+
+bool Depthbuffer::isDepthbuffer() const
+{
+ return true;
+}
+
+bool Depthbuffer::isStencilbuffer() const
+{
+ return false;
+}
+
+Stencilbuffer::Stencilbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil)
+{
+ if (depthStencil)
+ {
+ mFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
+ // will expect one of the valid renderbuffer formats for use in
+ // glRenderbufferStorage
+ }
+ else
+ {
+ mFormat = GL_RGBA4; //default format
+ }
+}
+
+Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
+{
+ if (getDepthStencil())
+ {
+ mFormat = 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()
+{
+}
+
+bool Stencilbuffer::isDepthbuffer() const
+{
+ return false;
+}
+
+bool Stencilbuffer::isStencilbuffer() const
+{
+ return true;
+}
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.h
new file mode 100644
index 0000000..cb8c06a
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.h
@@ -0,0 +1,175 @@
+//
+// 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 "libGLESv2/RefCountObject.h"
+
+namespace gl
+{
+
+// 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:
+ RenderbufferStorage();
+
+ virtual ~RenderbufferStorage() = 0;
+
+ virtual bool isColorbuffer() const;
+ virtual bool isDepthbuffer() const;
+ virtual bool isStencilbuffer() const;
+
+ virtual IDirect3DSurface9 *getRenderTarget();
+ virtual IDirect3DSurface9 *getDepthStencil();
+
+ virtual int getWidth() const;
+ virtual int getHeight() const;
+ virtual GLenum getFormat() const;
+ D3DFORMAT getD3DFormat() const;
+ GLsizei getSamples() const;
+ unsigned int getSerial() const;
+
+ static unsigned int issueSerial();
+
+ protected:
+ void setSize(int width, int height);
+ GLenum mFormat;
+ D3DFORMAT mD3DFormat;
+ GLsizei mSamples;
+ unsigned int mSerial;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RenderbufferStorage);
+
+ static unsigned int mCurrentSerial;
+
+ int mWidth;
+ int mHeight;
+};
+
+// Renderbuffer implements the GL renderbuffer object.
+// It's only a wrapper for a RenderbufferStorage, but the internal object
+// can change whenever glRenderbufferStorage is called.
+class Renderbuffer : public RefCountObject
+{
+ public:
+ Renderbuffer(GLuint id, RenderbufferStorage *storage);
+
+ ~Renderbuffer();
+
+ bool isColorbuffer() const;
+ bool isDepthbuffer() const;
+ bool isStencilbuffer() const;
+
+ IDirect3DSurface9 *getRenderTarget();
+ IDirect3DSurface9 *getDepthStencil();
+
+ int getWidth() const;
+ int getHeight() const;
+ GLenum getFormat() const;
+ D3DFORMAT getD3DFormat() const;
+ unsigned int getSerial() const;
+
+ void setStorage(RenderbufferStorage *newStorage);
+ RenderbufferStorage *getStorage() { return mStorage; }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Renderbuffer);
+
+ RenderbufferStorage *mStorage;
+};
+
+class Colorbuffer : public RenderbufferStorage
+{
+ public:
+ explicit Colorbuffer(IDirect3DSurface9 *renderTarget);
+ Colorbuffer(int width, int height, GLenum format, GLsizei samples);
+
+ ~Colorbuffer();
+
+ bool isColorbuffer() const;
+
+ GLuint getRedSize() const;
+ GLuint getGreenSize() const;
+ GLuint getBlueSize() const;
+ GLuint getAlphaSize() const;
+
+ IDirect3DSurface9 *getRenderTarget();
+
+ protected:
+ IDirect3DSurface9 *mRenderTarget;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Colorbuffer);
+};
+
+class DepthStencilbuffer : public RenderbufferStorage
+{
+ public:
+ explicit DepthStencilbuffer(IDirect3DSurface9 *depthStencil);
+ DepthStencilbuffer(int width, int height, GLsizei samples);
+
+ ~DepthStencilbuffer();
+
+ virtual bool isDepthbuffer() const;
+ virtual bool isStencilbuffer() const;
+
+ GLuint getDepthSize() const;
+ GLuint getStencilSize() const;
+
+ IDirect3DSurface9 *getDepthStencil();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DepthStencilbuffer);
+ IDirect3DSurface9 *mDepthStencil;
+};
+
+class Depthbuffer : public DepthStencilbuffer
+{
+ public:
+ explicit Depthbuffer(IDirect3DSurface9 *depthStencil);
+ Depthbuffer(int width, int height, GLsizei samples);
+
+ ~Depthbuffer();
+
+ bool isDepthbuffer() const;
+ bool isStencilbuffer() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Depthbuffer);
+};
+
+class Stencilbuffer : public DepthStencilbuffer
+{
+ public:
+ explicit Stencilbuffer(IDirect3DSurface9 *depthStencil);
+ Stencilbuffer(int width, int height, GLsizei samples);
+
+ ~Stencilbuffer();
+
+ bool isDepthbuffer() const;
+ bool isStencilbuffer() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Stencilbuffer);
+};
+}
+
+#endif // LIBGLESV2_RENDERBUFFER_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.cpp
new file mode 100644
index 0000000..12a86c1
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.cpp
@@ -0,0 +1,340 @@
+//
+// 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()
+{
+ unsigned int handle = 1;
+
+ while (mBufferMap.find(handle) != mBufferMap.end())
+ {
+ handle++;
+ }
+
+ mBufferMap[handle] = NULL;
+
+ return handle;
+}
+
+// Returns an unused shader/program name
+GLuint ResourceManager::createShader(GLenum type)
+{
+ unsigned int handle = 1;
+
+ while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end()) // Shared name space
+ {
+ handle++;
+ }
+
+ if (type == GL_VERTEX_SHADER)
+ {
+ mShaderMap[handle] = new VertexShader(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()
+{
+ unsigned int handle = 1;
+
+ while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end()) // Shared name space
+ {
+ handle++;
+ }
+
+ mProgramMap[handle] = new Program(this, handle);
+
+ return handle;
+}
+
+// Returns an unused texture name
+GLuint ResourceManager::createTexture()
+{
+ unsigned int handle = 1;
+
+ while (mTextureMap.find(handle) != mTextureMap.end())
+ {
+ handle++;
+ }
+
+ mTextureMap[handle] = NULL;
+
+ return handle;
+}
+
+// Returns an unused renderbuffer name
+GLuint ResourceManager::createRenderbuffer()
+{
+ unsigned int handle = 1;
+
+ while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
+ {
+ handle++;
+ }
+
+ mRenderbufferMap[handle] = NULL;
+
+ return handle;
+}
+
+void ResourceManager::deleteBuffer(GLuint buffer)
+{
+ BufferMap::iterator bufferObject = mBufferMap.find(buffer);
+
+ if (bufferObject != mBufferMap.end())
+ {
+ 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)
+ {
+ 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)
+ {
+ 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())
+ {
+ if (textureObject->second) textureObject->second->release();
+ mTextureMap.erase(textureObject);
+ }
+}
+
+void ResourceManager::deleteRenderbuffer(GLuint renderbuffer)
+{
+ RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
+
+ if (renderbufferObject != mRenderbufferMap.end())
+ {
+ 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, SamplerType type)
+{
+ if (!getTexture(texture) && texture != 0)
+ {
+ Texture *textureObject;
+
+ if (type == SAMPLER_2D)
+ {
+ textureObject = new Texture2D(texture);
+ }
+ else if (type == SAMPLER_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/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.h b/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.h
new file mode 100644
index 0000000..346e51f
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.h
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// 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>
+
+#include <map>
+
+#include "common/angleutils.h"
+
+namespace gl
+{
+class Buffer;
+class Shader;
+class Program;
+class Texture;
+class Renderbuffer;
+
+enum SamplerType
+{
+ SAMPLER_2D,
+ SAMPLER_CUBE,
+
+ SAMPLER_TYPE_COUNT
+};
+
+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, SamplerType type);
+ void checkRenderbufferAllocation(GLuint renderbuffer);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ResourceManager);
+
+ std::size_t mRefCount;
+
+ typedef std::map<GLuint, Buffer*> BufferMap;
+ BufferMap mBufferMap;
+
+ typedef std::map<GLuint, Shader*> ShaderMap;
+ ShaderMap mShaderMap;
+
+ typedef std::map<GLuint, Program*> ProgramMap;
+ ProgramMap mProgramMap;
+
+ typedef std::map<GLuint, Texture*> TextureMap;
+ TextureMap mTextureMap;
+
+ typedef std::map<GLuint, Renderbuffer*> RenderbufferMap;
+ RenderbufferMap mRenderbufferMap;
+};
+
+}
+
+#endif // LIBGLESV2_RESOURCEMANAGER_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.cpp
new file mode 100644
index 0000000..b73ef2a
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.cpp
@@ -0,0 +1,504 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Shader.cpp: Implements the gl::Shader class and its derived classes
+// VertexShader and FragmentShader. Implements GL shader objects and related
+// functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
+
+#include "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;
+
+ // Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
+ if (!mFragmentCompiler)
+ {
+ int result = ShInitialize();
+
+ if (result)
+ {
+ TBuiltInResource resources;
+ ShInitBuiltInResource(&resources);
+ resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
+ resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
+ resources.MaxVaryingVectors = MAX_VARYING_VECTORS;
+ resources.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
+ resources.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
+ resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+ resources.MaxFragmentUniformVectors = MAX_FRAGMENT_UNIFORM_VECTORS;
+ resources.MaxDrawBuffers = MAX_DRAW_BUFFERS;
+
+ mFragmentCompiler = ShConstructCompiler(EShLangFragment, EShSpecGLES2, &resources);
+ mVertexCompiler = ShConstructCompiler(EShLangVertex, EShSpecGLES2, &resources);
+ }
+ }
+
+ 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 (mInfoLog)
+ {
+ while (index < bufSize - 1 && index < (int)strlen(mInfoLog))
+ {
+ infoLog[index] = mInfoLog[index];
+ index++;
+ }
+ }
+
+ if (bufSize)
+ {
+ infoLog[index] = '\0';
+ }
+
+ if (length)
+ {
+ *length = index;
+ }
+}
+
+int Shader::getSourceLength() const
+{
+ if (!mSource)
+ {
+ return 0;
+ }
+ else
+ {
+ return strlen(mSource) + 1;
+ }
+}
+
+void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source)
+{
+ int index = 0;
+
+ if (mSource)
+ {
+ while (index < bufSize - 1 && index < (int)strlen(mSource))
+ {
+ source[index] = mSource[index];
+ index++;
+ }
+ }
+
+ if (bufSize)
+ {
+ source[index] = '\0';
+ }
+
+ if (length)
+ {
+ *length = index;
+ }
+}
+
+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;
+}
+
+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 %s %s", varyingType, varyingName);
+
+ if (matches != 2)
+ {
+ break;
+ }
+
+ char *array = strstr(varyingName, "[");
+ int size = 1;
+
+ if (array)
+ {
+ size = atoi(array + 1);
+ *array = '\0';
+ }
+
+ varyings.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;
+ }
+}
+
+void Shader::compileToHLSL(void *compiler)
+{
+ if (isCompiled() || !mSource)
+ {
+ return;
+ }
+
+ TRACE("\n%s", mSource);
+
+ delete[] mInfoLog;
+ mInfoLog = NULL;
+
+ int result = ShCompile(compiler, &mSource, 1, EShOptNone, EDebugOpNone);
+ const char *obj = ShGetObjectCode(compiler);
+ const char *info = ShGetInfoLog(compiler);
+
+ if (result)
+ {
+ mHlsl = new char[strlen(obj) + 1];
+ strcpy(mHlsl, obj);
+
+ TRACE("\n%s", mHlsl);
+ }
+ else
+ {
+ mInfoLog = new char[strlen(info) + 1];
+ strcpy(mInfoLog, info);
+
+ 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::compile()
+{
+ 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()
+{
+ if (mHlsl)
+ {
+ const char *input = strstr(mHlsl, "// Attributes") + 14;
+
+ while(true)
+ {
+ char attributeType[256];
+ char attributeName[256];
+
+ int matches = sscanf(input, "static %s _%s", 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()
+{
+ compileToHLSL(mFragmentCompiler);
+ parseVaryings();
+ varyings.sort(compareVarying);
+}
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.h
new file mode 100644
index 0000000..5eaa053
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.h
@@ -0,0 +1,157 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// 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 <d3dx9.h>
+#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 Program;
+
+ public:
+ Shader(ResourceManager *manager, GLuint handle);
+
+ virtual ~Shader();
+
+ virtual GLenum getType() = 0;
+ GLuint getHandle() const;
+
+ void deleteSource();
+ void setSource(GLsizei count, const char **string, const GLint *length);
+ int getInfoLogLength() const;
+ void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
+ int getSourceLength() const;
+ void getSource(GLsizei bufSize, GLsizei *length, char *source);
+
+ virtual void compile() = 0;
+ bool isCompiled();
+ const char *getHLSL();
+
+ void addRef();
+ void release();
+ unsigned int getRefCount() const;
+ bool isFlaggedForDeletion() const;
+ void flagForDeletion();
+
+ static void releaseCompiler();
+
+ protected:
+ DISALLOW_COPY_AND_ASSIGN(Shader);
+
+ void parseVaryings();
+
+ void compileToHLSL(void *compiler);
+
+ static GLenum parseType(const std::string &type);
+ static bool compareVarying(const Varying &x, const Varying &y);
+
+ 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;
+
+ VaryingList varyings;
+
+ bool mUsesFragCoord;
+ bool mUsesFrontFacing;
+ bool mUsesPointSize;
+ bool mUsesPointCoord;
+
+ ResourceManager *mResourceManager;
+
+ static void *mFragmentCompiler;
+ static void *mVertexCompiler;
+};
+
+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 Program;
+
+ public:
+ VertexShader(ResourceManager *manager, GLuint handle);
+
+ ~VertexShader();
+
+ GLenum getType();
+ void compile();
+ 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();
+
+ GLenum getType();
+ void compile();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FragmentShader);
+};
+}
+
+#endif // LIBGLESV2_SHADER_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp
new file mode 100644
index 0000000..2e0b1e3
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp
@@ -0,0 +1,1817 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Texture.cpp: Implements the gl::Texture class and its derived classes
+// Texture2D and TextureCubeMap. Implements GL texture objects and related
+// functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
+
+#include "libGLESv2/Texture.h"
+
+#include <algorithm>
+
+#include "common/debug.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/utilities.h"
+#include "libGLESv2/Blit.h"
+
+namespace gl
+{
+
+Texture::Image::Image()
+ : width(0), height(0), dirty(false), surface(NULL), format(GL_NONE)
+{
+}
+
+Texture::Image::~Image()
+{
+ if (surface) surface->Release();
+}
+
+Texture::Texture(GLuint id) : RefCountObject(id)
+{
+ mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
+ mMagFilter = GL_LINEAR;
+ mWrapS = GL_REPEAT;
+ mWrapT = GL_REPEAT;
+
+ mWidth = 0;
+ mHeight = 0;
+
+ mDirtyMetaData = true;
+ mDirty = true;
+ mIsRenderable = false;
+ mBaseTexture = NULL;
+}
+
+Texture::~Texture()
+{
+}
+
+Blit *Texture::getBlitter()
+{
+ Context *context = getContext();
+ return context->getBlitter();
+}
+
+// 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;
+ mDirty = 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;
+ mDirty = 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;
+ mDirty = 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;
+ mDirty = true;
+ }
+ 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;
+}
+
+GLuint Texture::getWidth() const
+{
+ return mWidth;
+}
+
+GLuint Texture::getHeight() const
+{
+ return mHeight;
+}
+
+// Selects an internal Direct3D 9 format for storing an Image
+D3DFORMAT Texture::selectFormat(GLenum format)
+{
+ if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
+ format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
+ {
+ return D3DFMT_DXT1;
+ }
+ else
+ {
+ return D3DFMT_A8R8G8B8;
+ }
+}
+
+int Texture::imagePitch(const Image &img) const
+{
+ return img.width * 4;
+}
+
+// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
+// into the BGRA8 pixel rectangle at output with outputPitch bytes in between each line.
+void Texture::loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,
+ GLint unpackAlignment, const void *input, size_t outputPitch, void *output) const
+{
+ GLsizei inputPitch = ComputePitch(width, format, type, unpackAlignment);
+
+ switch (format)
+ {
+ case GL_ALPHA:
+ loadAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ break;
+
+ case GL_LUMINANCE:
+ loadLuminanceImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ loadLuminanceAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ break;
+
+ case GL_RGB:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ loadRGBUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ break;
+
+ case GL_UNSIGNED_SHORT_5_6_5:
+ loadRGB565ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ break;
+
+ default: UNREACHABLE();
+ }
+ break;
+
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ loadRGBAUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ break;
+
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ loadRGBA4444ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ break;
+
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ loadRGBA5551ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ break;
+
+ default: UNREACHABLE();
+ }
+ break;
+ case GL_BGRA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ loadBGRAImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ break;
+
+ default: UNREACHABLE();
+ }
+ break;
+ default: UNREACHABLE();
+ }
+}
+
+void Texture::loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t 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 + yoffset) * outputPitch + xoffset * 4;
+ 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 Texture::loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t 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 + yoffset) * outputPitch + xoffset * 4;
+ 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;
+ }
+ }
+}
+
+void Texture::loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t 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 + yoffset) * outputPitch + xoffset * 4;
+ 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 Texture::loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t 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 + yoffset) * outputPitch + xoffset * 4;
+ for (int x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = source[x * 3 + 2];
+ dest[4 * x + 1] = source[x * 3 + 1];
+ dest[4 * x + 2] = source[x * 3 + 0];
+ dest[4 * x + 3] = 0xFF;
+ }
+ }
+}
+
+void Texture::loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t 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 + yoffset) * outputPitch + xoffset * 4;
+ for (int x = 0; x < width; x++)
+ {
+ unsigned short rgba = source[x];
+ dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
+ dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
+ dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
+ dest[4 * x + 3] = 0xFF;
+ }
+ }
+}
+
+void Texture::loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t 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 + yoffset) * outputPitch + xoffset * 4;
+ for (int x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = source[x * 4 + 2];
+ dest[4 * x + 1] = source[x * 4 + 1];
+ dest[4 * x + 2] = source[x * 4 + 0];
+ dest[4 * x + 3] = source[x * 4 + 3];
+ }
+ }
+}
+
+void Texture::loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t 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 + yoffset) * outputPitch + xoffset * 4;
+ for (int x = 0; x < width; x++)
+ {
+ unsigned short rgba = source[x];
+ dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
+ dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
+ dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
+ dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
+ }
+ }
+}
+
+void Texture::loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t 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 + yoffset) * outputPitch + xoffset * 4;
+ for (int x = 0; x < width; x++)
+ {
+ unsigned short rgba = source[x];
+ dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
+ dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
+ dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
+ dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
+ }
+ }
+}
+
+void Texture::loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t 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 + yoffset) * outputPitch + xoffset * 4;
+ memcpy(dest, source, width*4);
+ }
+}
+
+void Texture::createSurface(GLsizei width, GLsizei height, GLenum format, Image *img)
+{
+ IDirect3DTexture9 *newTexture = NULL;
+ IDirect3DSurface9 *newSurface = NULL;
+
+ if (width != 0 && height != 0)
+ {
+ int levelToFetch = 0;
+ GLsizei requestWidth = width;
+ GLsizei requestHeight = height;
+ if (IsCompressed(format) && (width % 4 != 0 || height % 4 != 0))
+ {
+ bool isMult4 = false;
+ int upsampleCount = 0;
+ while (!isMult4)
+ {
+ requestWidth <<= 1;
+ requestHeight <<= 1;
+ upsampleCount++;
+ if (requestWidth % 4 == 0 && requestHeight % 4 == 0)
+ {
+ isMult4 = true;
+ }
+ }
+ levelToFetch = upsampleCount;
+ }
+
+ HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, selectFormat(format),
+ D3DPOOL_SYSTEMMEM, &newTexture, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return error(GL_OUT_OF_MEMORY);
+ }
+
+ newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
+ newTexture->Release();
+ }
+
+ if (img->surface) img->surface->Release();
+ img->surface = newSurface;
+
+ img->width = width;
+ img->height = height;
+ img->format = format;
+}
+
+void Texture::setImage(GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img)
+{
+ createSurface(width, height, format, img);
+
+ if (pixels != NULL && img->surface != NULL)
+ {
+ D3DLOCKED_RECT locked;
+ HRESULT result = img->surface->LockRect(&locked, NULL, 0);
+
+ ASSERT(SUCCEEDED(result));
+
+ if (SUCCEEDED(result))
+ {
+ loadImageData(0, 0, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits);
+ img->surface->UnlockRect();
+ }
+
+ img->dirty = true;
+ }
+
+ mDirtyMetaData = true;
+}
+
+void Texture::setCompressedImage(GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img)
+{
+ createSurface(width, height, format, img);
+
+ if (pixels != NULL && img->surface != NULL)
+ {
+ D3DLOCKED_RECT locked;
+ HRESULT result = img->surface->LockRect(&locked, NULL, 0);
+
+ ASSERT(SUCCEEDED(result));
+
+ if (SUCCEEDED(result))
+ {
+ memcpy(locked.pBits, pixels, imageSize);
+ img->surface->UnlockRect();
+ }
+
+ img->dirty = true;
+ }
+
+ mDirtyMetaData = true;
+}
+
+bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img)
+{
+ if (width + xoffset > img->width || height + yoffset > img->height)
+ {
+ error(GL_INVALID_VALUE);
+ return false;
+ }
+
+ D3DLOCKED_RECT locked;
+ HRESULT result = img->surface->LockRect(&locked, NULL, 0);
+
+ ASSERT(SUCCEEDED(result));
+
+ if (SUCCEEDED(result))
+ {
+ loadImageData(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits);
+ img->surface->UnlockRect();
+ }
+
+ img->dirty = true;
+ return true;
+}
+
+bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img)
+{
+ if (width + xoffset > img->width || height + yoffset > img->height)
+ {
+ error(GL_INVALID_VALUE);
+ return false;
+ }
+
+ if (format != getFormat())
+ {
+ error(GL_INVALID_OPERATION);
+ return false;
+ }
+
+ RECT updateRegion;
+ updateRegion.left = xoffset;
+ updateRegion.right = xoffset + width;
+ updateRegion.bottom = yoffset + height;
+ updateRegion.top = yoffset;
+
+ D3DLOCKED_RECT locked;
+ HRESULT result = img->surface->LockRect(&locked, &updateRegion, 0);
+
+ ASSERT(SUCCEEDED(result));
+
+ if (SUCCEEDED(result))
+ {
+ GLsizei inputPitch = ComputeCompressedPitch(width, format);
+ int rows = imageSize / inputPitch;
+ for (int i = 0; i < rows; ++i)
+ {
+ memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)pixels + i * inputPitch), inputPitch);
+ }
+ img->surface->UnlockRect();
+ }
+
+ img->dirty = true;
+ return true;
+}
+
+IDirect3DBaseTexture9 *Texture::getTexture()
+{
+ if (!isComplete())
+ {
+ return NULL;
+ }
+
+ if (mDirtyMetaData)
+ {
+ mBaseTexture = createTexture();
+ mIsRenderable = false;
+ }
+
+ if (mDirtyMetaData || dirtyImageData())
+ {
+ updateTexture();
+ }
+
+ mDirtyMetaData = false;
+ ASSERT(!dirtyImageData());
+
+ return mBaseTexture;
+}
+
+bool Texture::isDirty() const
+{
+ return (mDirty || mDirtyMetaData || dirtyImageData());
+}
+
+// Returns the top-level texture surface as a render target
+void Texture::needRenderTarget()
+{
+ if (!mIsRenderable)
+ {
+ mBaseTexture = convertToRenderTarget();
+ mIsRenderable = true;
+ }
+
+ if (dirtyImageData())
+ {
+ updateTexture();
+ }
+
+ mDirtyMetaData = false;
+}
+
+void Texture::dropTexture()
+{
+ if (mBaseTexture)
+ {
+ mBaseTexture = NULL;
+ }
+
+ mIsRenderable = false;
+}
+
+void Texture::pushTexture(IDirect3DBaseTexture9 *newTexture, bool renderable)
+{
+ mBaseTexture = newTexture;
+ mDirtyMetaData = false;
+ mIsRenderable = renderable;
+ mDirty = true;
+}
+
+
+GLint Texture::creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const
+{
+ if (isPow2(width) && isPow2(height))
+ {
+ return maxlevel;
+ }
+ else
+ {
+ // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
+ return 1;
+ }
+}
+
+GLint Texture::creationLevels(GLsizei size, GLint maxlevel) const
+{
+ return creationLevels(size, size, maxlevel);
+}
+
+int Texture::levelCount() const
+{
+ return mBaseTexture ? mBaseTexture->GetLevelCount() : 0;
+}
+
+Texture2D::Texture2D(GLuint id) : Texture(id)
+{
+ mTexture = NULL;
+ mColorbufferProxy = NULL;
+}
+
+Texture2D::~Texture2D()
+{
+ delete mColorbufferProxy;
+
+ if (mTexture)
+ {
+ mTexture->Release();
+ mTexture = NULL;
+ }
+}
+
+GLenum Texture2D::getTarget() const
+{
+ return GL_TEXTURE_2D;
+}
+
+GLenum Texture2D::getFormat() const
+{
+ return mImageArray[0].format;
+}
+
+// While OpenGL doesn't check texture consistency until draw-time, D3D9 requires a complete texture
+// for render-to-texture (such as CopyTexImage). We have no way of keeping individual inconsistent levels.
+// Call this when a particular level of the texture must be defined with a specific format, width and height.
+//
+// Returns true if the existing texture was unsuitable had to be destroyed. If so, it will also set
+// a new height and width for the texture by working backwards from the given width and height.
+bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height)
+{
+ bool widthOkay = (mWidth >> level == width);
+ bool heightOkay = (mHeight >> level == height);
+
+ bool sizeOkay = ((widthOkay && heightOkay)
+ || (widthOkay && mHeight >> level == 0 && height == 1)
+ || (heightOkay && mWidth >> level == 0 && width == 1));
+
+ bool textureOkay = (sizeOkay && internalFormat == mImageArray[0].format);
+
+ if (!textureOkay)
+ {
+ TRACE("Redefining 2D texture (%d, 0x%04X, %d, %d => 0x%04X, %d, %d).", level,
+ mImageArray[0].format, mWidth, mHeight,
+ internalFormat, width, height);
+
+ // Purge all the levels and the texture.
+
+ for (int i = 0; i < MAX_TEXTURE_LEVELS; i++)
+ {
+ if (mImageArray[i].surface != NULL)
+ {
+ mImageArray[i].dirty = false;
+
+ mImageArray[i].surface->Release();
+ mImageArray[i].surface = NULL;
+ }
+ }
+
+ if (mTexture != NULL)
+ {
+ mTexture->Release();
+ mTexture = NULL;
+ dropTexture();
+ }
+
+ mWidth = width << level;
+ mHeight = height << level;
+ mImageArray[0].format = internalFormat;
+ }
+
+ return !textureOkay;
+}
+
+void Texture2D::setImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+ redefineTexture(level, internalFormat, width, height);
+
+ Texture::setImage(width, height, format, type, unpackAlignment, pixels, &mImageArray[level]);
+}
+
+void Texture2D::setCompressedImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
+{
+ redefineTexture(level, internalFormat, width, height);
+
+ Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[level]);
+}
+
+void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+ ASSERT(mImageArray[level].surface != NULL);
+
+ if (level < levelCount())
+ {
+ IDirect3DSurface9 *destLevel = NULL;
+ HRESULT result = mTexture->GetSurfaceLevel(level, &destLevel);
+
+ ASSERT(SUCCEEDED(result));
+
+ if (SUCCEEDED(result))
+ {
+ Image *img = &mImageArray[level];
+
+ RECT sourceRect;
+ sourceRect.left = xoffset;
+ sourceRect.top = yoffset;
+ sourceRect.right = xoffset + width;
+ sourceRect.bottom = yoffset + height;
+
+ POINT destPoint;
+ destPoint.x = xoffset;
+ destPoint.y = yoffset;
+
+ result = getDevice()->UpdateSurface(img->surface, &sourceRect, destLevel, &destPoint);
+ ASSERT(SUCCEEDED(result));
+
+ destLevel->Release();
+
+ img->dirty = false;
+ }
+ }
+}
+
+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 internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
+{
+ if (redefineTexture(level, internalFormat, width, height))
+ {
+ convertToRenderTarget();
+ pushTexture(mTexture, true);
+ }
+ else
+ {
+ needRenderTarget();
+ }
+
+ 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;
+ HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
+
+ getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
+ dest->Release();
+ }
+
+ mImageArray[level].width = width;
+ mImageArray[level].height = height;
+ mImageArray[level].format = internalFormat;
+}
+
+void Texture2D::copySubImage(GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
+{
+ if (xoffset + width > mImageArray[level].width || yoffset + height > mImageArray[level].height)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (redefineTexture(0, mImageArray[0].format, mImageArray[0].width, mImageArray[0].height))
+ {
+ convertToRenderTarget();
+ pushTexture(mTexture, true);
+ }
+ else
+ {
+ needRenderTarget();
+ }
+
+ if (level < levelCount())
+ {
+ RECT sourceRect;
+ sourceRect.left = x;
+ sourceRect.right = x + width;
+ sourceRect.top = y;
+ sourceRect.bottom = y + height;
+
+ IDirect3DSurface9 *dest;
+ HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
+
+ getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0].format, xoffset, yoffset, dest);
+ dest->Release();
+ }
+}
+
+// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool Texture2D::isComplete() const
+{
+ GLsizei width = mImageArray[0].width;
+ GLsizei height = mImageArray[0].height;
+
+ 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 ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width))
+ || (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height)))
+ {
+ return false;
+ }
+
+ if (mipmapping)
+ {
+ if (!isPow2(width) || !isPow2(height))
+ {
+ return false;
+ }
+
+ int q = log2(std::max(width, height));
+
+ for (int level = 1; level <= q; level++)
+ {
+ if (mImageArray[level].format != mImageArray[0].format)
+ {
+ return false;
+ }
+
+ if (mImageArray[level].width != std::max(1, width >> level))
+ {
+ return false;
+ }
+
+ if (mImageArray[level].height != std::max(1, height >> level))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool Texture2D::isCompressed() const
+{
+ return IsCompressed(getFormat());
+}
+
+// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
+IDirect3DBaseTexture9 *Texture2D::createTexture()
+{
+ IDirect3DTexture9 *texture;
+
+ IDirect3DDevice9 *device = getDevice();
+ D3DFORMAT format = selectFormat(mImageArray[0].format);
+
+ HRESULT result = device->CreateTexture(mWidth, mHeight, creationLevels(mWidth, mHeight, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+ }
+
+ if (mTexture) mTexture->Release();
+ mTexture = texture;
+ return texture;
+}
+
+void Texture2D::updateTexture()
+{
+ IDirect3DDevice9 *device = getDevice();
+
+ int levels = levelCount();
+
+ for (int level = 0; level < levels; level++)
+ {
+ if (mImageArray[level].dirty)
+ {
+ IDirect3DSurface9 *levelSurface = NULL;
+ HRESULT result = mTexture->GetSurfaceLevel(level, &levelSurface);
+
+ ASSERT(SUCCEEDED(result));
+
+ if (SUCCEEDED(result))
+ {
+ result = device->UpdateSurface(mImageArray[level].surface, NULL, levelSurface, NULL);
+ ASSERT(SUCCEEDED(result));
+
+ levelSurface->Release();
+
+ mImageArray[level].dirty = false;
+ }
+ }
+ }
+}
+
+IDirect3DBaseTexture9 *Texture2D::convertToRenderTarget()
+{
+ IDirect3DTexture9 *texture = NULL;
+
+ if (mWidth != 0 && mHeight != 0)
+ {
+ egl::Display *display = getDisplay();
+ IDirect3DDevice9 *device = getDevice();
+ D3DFORMAT format = selectFormat(mImageArray[0].format);
+
+ HRESULT result = device->CreateTexture(mWidth, mHeight, creationLevels(mWidth, mHeight, 0), D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+ }
+
+ if (mTexture != NULL)
+ {
+ int levels = levelCount();
+ for (int i = 0; i < levels; i++)
+ {
+ IDirect3DSurface9 *source;
+ result = mTexture->GetSurfaceLevel(i, &source);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+
+ texture->Release();
+
+ return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+ }
+
+ IDirect3DSurface9 *dest;
+ result = texture->GetSurfaceLevel(i, &dest);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+
+ texture->Release();
+ source->Release();
+
+ return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+ }
+
+ display->endScene();
+ result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+
+ texture->Release();
+ source->Release();
+ dest->Release();
+
+ return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+ }
+
+ source->Release();
+ dest->Release();
+ }
+ }
+ }
+
+ if (mTexture != NULL)
+ {
+ mTexture->Release();
+ }
+
+ mTexture = texture;
+ return mTexture;
+}
+
+bool Texture2D::dirtyImageData() const
+{
+ int q = log2(std::max(mWidth, mHeight));
+
+ for (int i = 0; i <= q; i++)
+ {
+ if (mImageArray[i].dirty) return true;
+ }
+
+ return false;
+}
+
+void Texture2D::generateMipmaps()
+{
+ if (!isPow2(mImageArray[0].width) || !isPow2(mImageArray[0].height))
+ {
+ 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(mWidth, mHeight));
+ for (unsigned int i = 1; i <= q; i++)
+ {
+ if (mImageArray[i].surface != NULL)
+ {
+ mImageArray[i].surface->Release();
+ mImageArray[i].surface = NULL;
+ }
+
+ mImageArray[i].dirty = false;
+
+ mImageArray[i].format = mImageArray[0].format;
+ mImageArray[i].width = std::max(mImageArray[0].width >> i, 1);
+ mImageArray[i].height = std::max(mImageArray[0].height >> i, 1);
+ }
+
+ needRenderTarget();
+
+ for (unsigned int i = 1; i <= q; i++)
+ {
+ IDirect3DSurface9 *upper = NULL;
+ IDirect3DSurface9 *lower = NULL;
+
+ mTexture->GetSurfaceLevel(i-1, &upper);
+ mTexture->GetSurfaceLevel(i, &lower);
+
+ if (upper != NULL && lower != NULL)
+ {
+ getBlitter()->boxFilter(upper, lower);
+ }
+
+ if (upper != NULL) upper->Release();
+ if (lower != NULL) lower->Release();
+ }
+}
+
+Renderbuffer *Texture2D::getColorbuffer(GLenum target)
+{
+ if (target != GL_TEXTURE_2D)
+ {
+ return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
+ }
+
+ if (mColorbufferProxy == NULL)
+ {
+ mColorbufferProxy = new Renderbuffer(id(), new TextureColorbufferProxy(this, target));
+ mColorbufferProxy->addRef();
+ }
+
+ return mColorbufferProxy;
+}
+
+IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)
+{
+ ASSERT(target == GL_TEXTURE_2D);
+
+ needRenderTarget();
+
+ IDirect3DSurface9 *renderTarget = NULL;
+ mTexture->GetSurfaceLevel(0, &renderTarget);
+
+ return renderTarget;
+}
+
+TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id)
+{
+ mTexture = NULL;
+
+ for (int i = 0; i < 6; i++)
+ {
+ mFaceProxies[i] = NULL;
+ }
+}
+
+TextureCubeMap::~TextureCubeMap()
+{
+ for (int i = 0; i < 6; i++)
+ {
+ delete mFaceProxies[i];
+ }
+
+ if (mTexture)
+ {
+ mTexture->Release();
+ mTexture = NULL;
+ }
+}
+
+GLenum TextureCubeMap::getTarget() const
+{
+ return GL_TEXTURE_CUBE_MAP;
+}
+
+GLenum TextureCubeMap::getFormat() const
+{
+ return mImageArray[0][0].format;
+}
+
+void TextureCubeMap::setImagePosX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+ setImage(0, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setImageNegX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+ setImage(1, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setImagePosY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+ setImage(2, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setImageNegY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+ setImage(3, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setImagePosZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+ setImage(4, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setImageNegZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+ setImage(5, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
+{
+ redefineTexture(level, internalFormat, width);
+
+ Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[faceIndex(face)][level]);
+}
+
+void TextureCubeMap::commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+ int face = faceIndex(faceTarget);
+
+ ASSERT(mImageArray[face][level].surface != NULL);
+
+ if (level < levelCount())
+ {
+ IDirect3DSurface9 *destLevel = getCubeMapSurface(face, level);
+ ASSERT(destLevel != NULL);
+
+ if (destLevel != NULL)
+ {
+ Image *img = &mImageArray[face][level];
+
+ RECT sourceRect;
+ sourceRect.left = xoffset;
+ sourceRect.top = yoffset;
+ sourceRect.right = xoffset + width;
+ sourceRect.bottom = yoffset + height;
+
+ POINT destPoint;
+ destPoint.x = xoffset;
+ destPoint.y = yoffset;
+
+ HRESULT result = getDevice()->UpdateSurface(img->surface, &sourceRect, destLevel, &destPoint);
+ ASSERT(SUCCEEDED(result));
+
+ destLevel->Release();
+
+ img->dirty = false;
+ }
+ }
+}
+
+void TextureCubeMap::subImage(GLenum face, 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(face)][level]))
+ {
+ commitRect(face, level, xoffset, yoffset, width, height);
+ }
+}
+
+void TextureCubeMap::subImageCompressed(GLenum face, 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(face)][level]))
+ {
+ commitRect(face, level, xoffset, yoffset, width, height);
+ }
+}
+
+// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool TextureCubeMap::isComplete() const
+{
+ int size = mImageArray[0][0].width;
+
+ if (size <= 0)
+ {
+ return false;
+ }
+
+ 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();
+ }
+
+ for (int face = 0; face < 6; face++)
+ {
+ if (mImageArray[face][0].width != size || mImageArray[face][0].height != size)
+ {
+ return false;
+ }
+ }
+
+ if (mipmapping)
+ {
+ if (!isPow2(size) && (getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE))
+ {
+ return false;
+ }
+
+ int q = log2(size);
+
+ for (int face = 0; face < 6; face++)
+ {
+ for (int level = 1; level <= q; level++)
+ {
+ if (mImageArray[face][level].format != mImageArray[0][0].format)
+ {
+ return false;
+ }
+
+ if (mImageArray[face][level].width != std::max(1, size >> level))
+ {
+ return false;
+ }
+
+ ASSERT(mImageArray[face][level].height == mImageArray[face][level].width);
+ }
+ }
+ }
+
+ return true;
+}
+
+bool TextureCubeMap::isCompressed() const
+{
+ return IsCompressed(getFormat());
+}
+
+// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
+IDirect3DBaseTexture9 *TextureCubeMap::createTexture()
+{
+ IDirect3DDevice9 *device = getDevice();
+ D3DFORMAT format = selectFormat(mImageArray[0][0].format);
+
+ IDirect3DCubeTexture9 *texture;
+
+ HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+ }
+
+ if (mTexture) mTexture->Release();
+
+ mTexture = texture;
+ return mTexture;
+}
+
+void TextureCubeMap::updateTexture()
+{
+ IDirect3DDevice9 *device = getDevice();
+
+ for (int face = 0; face < 6; face++)
+ {
+ int levels = levelCount();
+ for (int level = 0; level < levels; level++)
+ {
+ Image *img = &mImageArray[face][level];
+
+ if (img->dirty)
+ {
+ IDirect3DSurface9 *levelSurface = getCubeMapSurface(face, level);
+ ASSERT(levelSurface != NULL);
+
+ if (levelSurface != NULL)
+ {
+ HRESULT result = device->UpdateSurface(img->surface, NULL, levelSurface, NULL);
+ ASSERT(SUCCEEDED(result));
+
+ levelSurface->Release();
+
+ img->dirty = false;
+ }
+ }
+ }
+ }
+}
+
+IDirect3DBaseTexture9 *TextureCubeMap::convertToRenderTarget()
+{
+ IDirect3DCubeTexture9 *texture = NULL;
+
+ if (mWidth != 0)
+ {
+ egl::Display *display = getDisplay();
+ IDirect3DDevice9 *device = getDevice();
+ D3DFORMAT format = selectFormat(mImageArray[0][0].format);
+
+ HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+ }
+
+ if (mTexture != NULL)
+ {
+ int levels = levelCount();
+ for (int f = 0; f < 6; f++)
+ {
+ for (int i = 0; i < levels; i++)
+ {
+ IDirect3DSurface9 *source;
+ result = mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &source);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+
+ texture->Release();
+
+ return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+ }
+
+ IDirect3DSurface9 *dest;
+ result = texture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &dest);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+
+ texture->Release();
+ source->Release();
+
+ return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+ }
+
+ display->endScene();
+ result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+
+ texture->Release();
+ source->Release();
+ dest->Release();
+
+ return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+ }
+ }
+ }
+ }
+ }
+
+ if (mTexture != NULL)
+ {
+ mTexture->Release();
+ }
+
+ mTexture = texture;
+ return mTexture;
+}
+
+void TextureCubeMap::setImage(int face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+ redefineTexture(level, internalFormat, width);
+
+ Texture::setImage(width, height, format, type, unpackAlignment, pixels, &mImageArray[face][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;
+}
+
+bool TextureCubeMap::dirtyImageData() const
+{
+ int q = log2(mWidth);
+
+ for (int f = 0; f < 6; f++)
+ {
+ for (int i = 0; i <= q; i++)
+ {
+ if (mImageArray[f][i].dirty) return true;
+ }
+ }
+
+ return false;
+}
+
+// While OpenGL doesn't check texture consistency until draw-time, D3D9 requires a complete texture
+// for render-to-texture (such as CopyTexImage). We have no way of keeping individual inconsistent levels & faces.
+// Call this when a particular level of the texture must be defined with a specific format, width and height.
+//
+// Returns true if the existing texture was unsuitable had to be destroyed. If so, it will also set
+// a new size for the texture by working backwards from the given size.
+bool TextureCubeMap::redefineTexture(GLint level, GLenum internalFormat, GLsizei width)
+{
+ // Are these settings compatible with level 0?
+ bool sizeOkay = (mImageArray[0][0].width >> level == width);
+
+ bool textureOkay = (sizeOkay && internalFormat == mImageArray[0][0].format);
+
+ if (!textureOkay)
+ {
+ TRACE("Redefining cube texture (%d, 0x%04X, %d => 0x%04X, %d).", level,
+ mImageArray[0][0].format, mImageArray[0][0].width,
+ internalFormat, width);
+
+ // Purge all the levels and the texture.
+ for (int i = 0; i < MAX_TEXTURE_LEVELS; i++)
+ {
+ for (int f = 0; f < 6; f++)
+ {
+ if (mImageArray[f][i].surface != NULL)
+ {
+ mImageArray[f][i].dirty = false;
+
+ mImageArray[f][i].surface->Release();
+ mImageArray[f][i].surface = NULL;
+ }
+ }
+ }
+
+ if (mTexture != NULL)
+ {
+ mTexture->Release();
+ mTexture = NULL;
+ dropTexture();
+ }
+
+ mWidth = width << level;
+ mImageArray[0][0].width = width << level;
+ mHeight = width << level;
+ mImageArray[0][0].height = width << level;
+
+ mImageArray[0][0].format = internalFormat;
+ }
+
+ return !textureOkay;
+}
+
+void TextureCubeMap::copyImage(GLenum face, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
+{
+ unsigned int faceindex = faceIndex(face);
+
+ if (redefineTexture(level, internalFormat, width))
+ {
+ convertToRenderTarget();
+ pushTexture(mTexture, true);
+ }
+ else
+ {
+ needRenderTarget();
+ }
+
+ 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 = getCubeMapSurface(face, level);
+
+ getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
+ dest->Release();
+ }
+
+ mImageArray[faceindex][level].width = width;
+ mImageArray[faceindex][level].height = height;
+ mImageArray[faceindex][level].format = internalFormat;
+}
+
+IDirect3DSurface9 *TextureCubeMap::getCubeMapSurface(unsigned int faceIdentifier, unsigned int level)
+{
+ unsigned int faceIndex;
+
+ if (faceIdentifier < 6)
+ {
+ faceIndex = faceIdentifier;
+ }
+ else if (faceIdentifier >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && faceIdentifier <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
+ {
+ faceIndex = faceIdentifier - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ }
+ else
+ {
+ UNREACHABLE();
+ faceIndex = 0;
+ }
+
+ if (mTexture == NULL)
+ {
+ UNREACHABLE();
+ return NULL;
+ }
+
+ IDirect3DSurface9 *surface = NULL;
+
+ HRESULT hr = mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(faceIndex), level, &surface);
+
+ return (SUCCEEDED(hr)) ? surface : NULL;
+}
+
+void TextureCubeMap::copySubImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
+{
+ GLsizei size = mImageArray[faceIndex(face)][level].width;
+
+ if (xoffset + width > size || yoffset + height > size)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (redefineTexture(0, mImageArray[0][0].format, mImageArray[0][0].width))
+ {
+ convertToRenderTarget();
+ pushTexture(mTexture, true);
+ }
+ else
+ {
+ needRenderTarget();
+ }
+
+ if (level < levelCount())
+ {
+ RECT sourceRect;
+ sourceRect.left = x;
+ sourceRect.right = x + width;
+ sourceRect.top = y;
+ sourceRect.bottom = y + height;
+
+ IDirect3DSurface9 *dest = getCubeMapSurface(face, level);
+
+ getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0][0].format, xoffset, yoffset, dest);
+ dest->Release();
+ }
+}
+
+bool TextureCubeMap::isCubeComplete() const
+{
+ if (mImageArray[0][0].width == 0)
+ {
+ return false;
+ }
+
+ for (unsigned int f = 1; f < 6; f++)
+ {
+ if (mImageArray[f][0].width != mImageArray[0][0].width
+ || mImageArray[f][0].format != mImageArray[0][0].format)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void TextureCubeMap::generateMipmaps()
+{
+ if (!isPow2(mImageArray[0][0].width) || !isCubeComplete())
+ {
+ 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].width);
+ for (unsigned int f = 0; f < 6; f++)
+ {
+ for (unsigned int i = 1; i <= q; i++)
+ {
+ if (mImageArray[f][i].surface != NULL)
+ {
+ mImageArray[f][i].surface->Release();
+ mImageArray[f][i].surface = NULL;
+ }
+
+ mImageArray[f][i].dirty = false;
+
+ mImageArray[f][i].format = mImageArray[f][0].format;
+ mImageArray[f][i].width = std::max(mImageArray[f][0].width >> i, 1);
+ mImageArray[f][i].height = mImageArray[f][i].width;
+ }
+ }
+
+ needRenderTarget();
+
+ for (unsigned int f = 0; f < 6; f++)
+ {
+ for (unsigned int i = 1; i <= q; i++)
+ {
+ IDirect3DSurface9 *upper = getCubeMapSurface(f, i-1);
+ IDirect3DSurface9 *lower = getCubeMapSurface(f, i);
+
+ if (upper != NULL && lower != NULL)
+ {
+ getBlitter()->boxFilter(upper, lower);
+ }
+
+ if (upper != NULL) upper->Release();
+ if (lower != NULL) lower->Release();
+ }
+ }
+}
+
+Renderbuffer *TextureCubeMap::getColorbuffer(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 TextureColorbufferProxy(this, target));
+ mFaceProxies[face]->addRef();
+ }
+
+ return mFaceProxies[face];
+}
+
+IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)
+{
+ ASSERT(IsCubemapTextureTarget(target));
+
+ needRenderTarget();
+
+ IDirect3DSurface9 *renderTarget = NULL;
+ mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(faceIndex(target)), 0, &renderTarget);
+
+ return renderTarget;
+}
+
+Texture::TextureColorbufferProxy::TextureColorbufferProxy(Texture *texture, GLenum target)
+ : Colorbuffer(NULL), mTexture(texture), mTarget(target)
+{
+ ASSERT(target == GL_TEXTURE_2D || IsCubemapTextureTarget(target));
+}
+
+void Texture::TextureColorbufferProxy::addRef() const
+{
+ mTexture->addRef();
+}
+
+void Texture::TextureColorbufferProxy::release() const
+{
+ mTexture->release();
+}
+
+IDirect3DSurface9 *Texture::TextureColorbufferProxy::getRenderTarget()
+{
+ if (mRenderTarget) mRenderTarget->Release();
+
+ mRenderTarget = mTexture->getRenderTarget(mTarget);
+
+ return mRenderTarget;
+}
+
+int Texture::TextureColorbufferProxy::getWidth() const
+{
+ return mTexture->getWidth();
+}
+
+int Texture::TextureColorbufferProxy::getHeight() const
+{
+ return mTexture->getHeight();
+}
+
+GLenum Texture::TextureColorbufferProxy::getFormat() const
+{
+ return mTexture->getFormat();
+}
+
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.h
new file mode 100644
index 0000000..efa882c
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.h
@@ -0,0 +1,283 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Texture.h: Defines the abstract gl::Texture class and its concrete derived
+// classes Texture2D and TextureCubeMap. Implements GL texture objects and
+// related functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
+
+#ifndef LIBGLESV2_TEXTURE_H_
+#define LIBGLESV2_TEXTURE_H_
+
+#include <vector>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <d3d9.h>
+
+#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/utilities.h"
+#include "common/debug.h"
+
+namespace gl
+{
+class Blit;
+
+enum
+{
+ MAX_TEXTURE_SIZE = 2048,
+ MAX_CUBE_MAP_TEXTURE_SIZE = 2048,
+
+ MAX_TEXTURE_LEVELS = 12 // 1+log2 of MAX_TEXTURE_SIZE
+};
+
+class Texture : public RefCountObject
+{
+ public:
+ explicit Texture(GLuint id);
+
+ virtual ~Texture();
+
+ virtual GLenum getTarget() const = 0;
+
+ bool setMinFilter(GLenum filter);
+ bool setMagFilter(GLenum filter);
+ bool setWrapS(GLenum wrap);
+ bool setWrapT(GLenum wrap);
+
+ GLenum getMinFilter() const;
+ GLenum getMagFilter() const;
+ GLenum getWrapS() const;
+ GLenum getWrapT() const;
+
+ GLuint getWidth() const;
+ GLuint getHeight() const;
+
+ virtual GLenum getFormat() const = 0;
+ virtual bool isComplete() const = 0;
+ virtual bool isCompressed() const = 0;
+
+ IDirect3DBaseTexture9 *getTexture();
+ virtual Renderbuffer *getColorbuffer(GLenum target) = 0;
+
+ virtual void generateMipmaps() = 0;
+
+ bool isDirty() const;
+
+ 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:
+ class TextureColorbufferProxy;
+ friend class TextureColorbufferProxy;
+ class TextureColorbufferProxy : public Colorbuffer
+ {
+ public:
+ TextureColorbufferProxy(Texture *texture, GLenum target);
+ // target is a 2D-like texture target (GL_TEXTURE_2D or one of the cube face targets)
+
+ virtual void addRef() const;
+ virtual void release() const;
+
+ virtual IDirect3DSurface9 *getRenderTarget();
+
+ virtual int getWidth() const;
+ virtual int getHeight() const;
+ virtual GLenum getFormat() const;
+
+ private:
+ Texture *mTexture;
+ GLenum mTarget;
+ };
+
+ // Helper structure representing a single image layer
+ struct Image
+ {
+ Image();
+ ~Image();
+
+ GLsizei width;
+ GLsizei height;
+ GLenum format;
+
+ bool dirty;
+
+ IDirect3DSurface9 *surface;
+ };
+
+ static D3DFORMAT selectFormat(GLenum format);
+ int imagePitch(const Image& img) const;
+
+ void setImage(GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img);
+ bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img);
+ void setCompressedImage(GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img);
+ bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img);
+
+ void needRenderTarget();
+
+ GLint creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const;
+ GLint creationLevels(GLsizei size, GLint maxlevel) const;
+
+ // The pointer returned is weak and it is assumed the derived class will keep a strong pointer until the next createTexture() call.
+ virtual IDirect3DBaseTexture9 *createTexture() = 0;
+ virtual void updateTexture() = 0;
+ virtual IDirect3DBaseTexture9 *convertToRenderTarget() = 0;
+ virtual IDirect3DSurface9 *getRenderTarget(GLenum target) = 0;
+
+ virtual bool dirtyImageData() const = 0;
+
+ void dropTexture();
+ void pushTexture(IDirect3DBaseTexture9 *newTexture, bool renderable);
+
+ Blit *getBlitter();
+
+ int levelCount() const;
+
+ unsigned int mWidth;
+ unsigned int mHeight;
+ GLenum mMinFilter;
+ GLenum mMagFilter;
+ GLenum mWrapS;
+ GLenum mWrapT;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Texture);
+
+ void loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,
+ GLint unpackAlignment, const void *input, std::size_t outputPitch, void *output) const;
+
+ void loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
+
+ IDirect3DBaseTexture9 *mBaseTexture; // This is a weak pointer. The derived class is assumed to own a strong pointer.
+
+ bool mDirty;
+ bool mDirtyMetaData;
+ bool mIsRenderable;
+
+ void createSurface(GLsizei width, GLsizei height, GLenum format, Image *img);
+};
+
+class Texture2D : public Texture
+{
+ public:
+ explicit Texture2D(GLuint id);
+
+ ~Texture2D();
+
+ GLenum getTarget() const;
+ GLenum getFormat() const;
+
+ void setImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void setCompressedImage(GLint level, GLenum internalFormat, 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 internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
+ void copySubImage(GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
+
+ bool isComplete() const;
+ bool isCompressed() const;
+
+ virtual void generateMipmaps();
+
+ virtual Renderbuffer *getColorbuffer(GLenum target);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Texture2D);
+
+ virtual IDirect3DBaseTexture9 *createTexture();
+ virtual void updateTexture();
+ virtual IDirect3DBaseTexture9 *convertToRenderTarget();
+ virtual IDirect3DSurface9 *getRenderTarget(GLenum target);
+
+ virtual bool dirtyImageData() const;
+
+ bool redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height);
+ void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+
+ Image mImageArray[MAX_TEXTURE_LEVELS];
+
+ IDirect3DTexture9 *mTexture;
+
+ Renderbuffer *mColorbufferProxy;
+};
+
+class TextureCubeMap : public Texture
+{
+ public:
+ explicit TextureCubeMap(GLuint id);
+
+ ~TextureCubeMap();
+
+ GLenum getTarget() const;
+ GLenum getFormat() const;
+
+ void setImagePosX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void setImageNegX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void setImagePosY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void setImageNegY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void setImagePosZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void setImageNegZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+
+ void setCompressedImage(GLenum face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
+
+ void subImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void subImageCompressed(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
+ void copyImage(GLenum face, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
+ void copySubImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
+
+ bool isComplete() const;
+ bool isCompressed() const;
+
+ virtual void generateMipmaps();
+
+ virtual Renderbuffer *getColorbuffer(GLenum target);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
+
+ virtual IDirect3DBaseTexture9 *createTexture();
+ virtual void updateTexture();
+ virtual IDirect3DBaseTexture9 *convertToRenderTarget();
+ virtual IDirect3DSurface9 *getRenderTarget(GLenum target);
+
+ virtual bool dirtyImageData() const;
+
+ // faceIdentifier is 0-5 or one of the GL_TEXTURE_CUBE_MAP_* enumerants.
+ // Returns NULL if the call underlying Direct3D call fails.
+ IDirect3DSurface9 *getCubeMapSurface(unsigned int faceIdentifier, unsigned int level);
+
+ static unsigned int faceIndex(GLenum face);
+
+ bool isCubeComplete() const;
+
+ void setImage(int face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+ bool redefineTexture(GLint level, GLenum internalFormat, GLsizei width);
+
+ Image mImageArray[6][MAX_TEXTURE_LEVELS];
+
+ IDirect3DCubeTexture9 *mTexture;
+
+ Renderbuffer *mFaceProxies[6];
+};
+}
+
+#endif // LIBGLESV2_TEXTURE_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp
new file mode 100644
index 0000000..d573579
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp
@@ -0,0 +1,261 @@
+//
+// 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.
+//
+
+// geometry/IndexDataManager.cpp: Defines the IndexDataManager, a class that
+// runs the Buffer translation process for index buffers.
+
+#include "libGLESv2/geometry/IndexDataManager.h"
+
+#include "common/debug.h"
+
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/geometry/backend.h"
+
+namespace
+{
+ enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
+}
+
+namespace gl
+{
+
+IndexDataManager::IndexDataManager(Context *context, BufferBackEnd *backend)
+ : mContext(context), mBackend(backend), mIntIndicesSupported(backend->supportIntIndices())
+{
+ mCountingBuffer = NULL;
+ mCountingBufferSize = 0;
+
+ mLineLoopBuffer = NULL;
+
+ mStreamBufferShort = mBackend->createIndexBuffer(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT);
+
+ if (mIntIndicesSupported)
+ {
+ mStreamBufferInt = mBackend->createIndexBuffer(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
+ }
+ else
+ {
+ mStreamBufferInt = NULL;
+ }
+}
+
+IndexDataManager::~IndexDataManager()
+{
+ delete mStreamBufferShort;
+ delete mStreamBufferInt;
+ delete mCountingBuffer;
+ delete mLineLoopBuffer;
+}
+
+namespace
+{
+
+template <class InputIndexType, class OutputIndexType>
+void copyIndices(const InputIndexType *in, GLsizei count, OutputIndexType *out, GLuint *minIndex, GLuint *maxIndex)
+{
+ InputIndexType first = *in;
+ GLuint minIndexSoFar = first;
+ GLuint maxIndexSoFar = first;
+
+ for (GLsizei i = 0; i < count; i++)
+ {
+ if (minIndexSoFar > *in) minIndexSoFar = *in;
+ if (maxIndexSoFar < *in) maxIndexSoFar = *in;
+
+ *out++ = *in++;
+ }
+
+ // It might be a line loop, so copy the loop index.
+ *out = first;
+
+ *minIndex = minIndexSoFar;
+ *maxIndex = maxIndexSoFar;
+}
+
+}
+
+GLenum IndexDataManager::preRenderValidate(GLenum mode, GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices, TranslatedIndexData *translated)
+{
+ ASSERT(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT);
+ ASSERT(count > 0);
+
+ if (arrayElementBuffer != NULL)
+ {
+ GLsizei offset = reinterpret_cast<GLsizei>(indices);
+
+ if (typeSize(type) * count + offset > static_cast<std::size_t>(arrayElementBuffer->size()))
+ {
+ return GL_INVALID_OPERATION;
+ }
+
+ indices = static_cast<const GLubyte*>(arrayElementBuffer->data()) + offset;
+ }
+
+ translated->count = count;
+
+ std::size_t requiredSpace = spaceRequired(type, count);
+
+ TranslatedIndexBuffer *streamIb = prepareIndexBuffer(type, requiredSpace);
+
+ size_t offset;
+ void *output = streamIb->map(requiredSpace, &offset);
+
+ translated->buffer = streamIb;
+ translated->offset = offset;
+ translated->indexSize = indexSize(type);
+
+ if (type == GL_UNSIGNED_BYTE)
+ {
+ const GLubyte *in = static_cast<const GLubyte*>(indices);
+ GLushort *out = static_cast<GLushort*>(output);
+
+ copyIndices(in, count, out, &translated->minIndex, &translated->maxIndex);
+ }
+ else if (type == GL_UNSIGNED_INT)
+ {
+ const GLuint *in = static_cast<const GLuint*>(indices);
+
+ if (mIntIndicesSupported)
+ {
+ GLuint *out = static_cast<GLuint*>(output);
+
+ copyIndices(in, count, out, &translated->minIndex, &translated->maxIndex);
+ }
+ else
+ {
+ // When 32-bit indices are unsupported, fake them by truncating to 16-bit.
+
+ GLushort *out = static_cast<GLushort*>(output);
+
+ copyIndices(in, count, out, &translated->minIndex, &translated->maxIndex);
+ }
+ }
+ else
+ {
+ const GLushort *in = static_cast<const GLushort*>(indices);
+ GLushort *out = static_cast<GLushort*>(output);
+
+ copyIndices(in, count, out, &translated->minIndex, &translated->maxIndex);
+ }
+
+ streamIb->unmap();
+
+ return GL_NO_ERROR;
+}
+
+std::size_t IndexDataManager::indexSize(GLenum type) const
+{
+ return (type == GL_UNSIGNED_INT && mIntIndicesSupported) ? sizeof(GLuint) : sizeof(GLushort);
+}
+
+std::size_t IndexDataManager::typeSize(GLenum type) const
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT: return sizeof(GLuint);
+ case GL_UNSIGNED_SHORT: return sizeof(GLushort);
+ default: UNREACHABLE();
+ case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
+ }
+}
+
+std::size_t IndexDataManager::spaceRequired(GLenum type, GLsizei count) const
+{
+ return (count + 1) * indexSize(type); // +1 because we always leave an extra for line loops
+}
+
+TranslatedIndexBuffer *IndexDataManager::prepareIndexBuffer(GLenum type, std::size_t requiredSpace)
+{
+ bool use32 = (type == GL_UNSIGNED_INT && mIntIndicesSupported);
+
+ TranslatedIndexBuffer *streamIb = use32 ? mStreamBufferInt : mStreamBufferShort;
+
+ if (requiredSpace > streamIb->size())
+ {
+ std::size_t newSize = std::max(requiredSpace, 2 * streamIb->size());
+
+ TranslatedIndexBuffer *newStreamBuffer = mBackend->createIndexBuffer(newSize, use32 ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT);
+
+ delete streamIb;
+
+ streamIb = newStreamBuffer;
+
+ if (use32)
+ {
+ mStreamBufferInt = streamIb;
+ }
+ else
+ {
+ mStreamBufferShort = streamIb;
+ }
+ }
+
+ streamIb->reserveSpace(requiredSpace);
+
+ return streamIb;
+}
+
+GLenum IndexDataManager::preRenderValidateUnindexed(GLenum mode, GLsizei count, TranslatedIndexData *indexInfo)
+{
+ if (count >= 65535) return GL_OUT_OF_MEMORY;
+
+ if (mode == GL_LINE_LOOP)
+ {
+ // For line loops, create a single-use buffer that runs 0 - count-1, 0.
+ delete mLineLoopBuffer;
+ mLineLoopBuffer = mBackend->createIndexBuffer((count+1) * sizeof(unsigned short), GL_UNSIGNED_SHORT);
+
+ unsigned short *indices = static_cast<unsigned short *>(mLineLoopBuffer->map());
+
+ for (int i = 0; i < count; i++)
+ {
+ indices[i] = i;
+ }
+
+ indices[count] = 0;
+
+ mLineLoopBuffer->unmap();
+
+ indexInfo->buffer = mLineLoopBuffer;
+ indexInfo->count = count + 1;
+ indexInfo->maxIndex = count - 1;
+ }
+ else if (mCountingBufferSize < count)
+ {
+ mCountingBufferSize = std::max(static_cast<GLsizei>(ceilPow2(count)), mCountingBufferSize*2);
+
+ delete mCountingBuffer;
+ mCountingBuffer = mBackend->createIndexBuffer(count * sizeof(unsigned short), GL_UNSIGNED_SHORT);
+
+ unsigned short *indices = static_cast<unsigned short *>(mCountingBuffer->map());
+
+ for (int i = 0; i < count; i++)
+ {
+ indices[i] = i;
+ }
+
+ mCountingBuffer->unmap();
+
+ indexInfo->buffer = mCountingBuffer;
+ indexInfo->count = count;
+ indexInfo->maxIndex = count - 1;
+ }
+ else
+ {
+ indexInfo->buffer = mCountingBuffer;
+ indexInfo->count = count;
+ indexInfo->maxIndex = count - 1;
+ }
+
+ indexInfo->indexSize = sizeof(unsigned short);
+ indexInfo->minIndex = 0;
+ indexInfo->offset = 0;
+
+ return GL_NO_ERROR;
+}
+
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.h b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.h
new file mode 100644
index 0000000..00ebed2
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.h
@@ -0,0 +1,71 @@
+//
+// 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.
+//
+
+// geometry/IndexDataManager.h: Defines the IndexDataManager, a class that
+// runs the Buffer translation process for index buffers.
+
+#ifndef LIBGLESV2_GEOMETRY_INDEXDATAMANAGER_H_
+#define LIBGLESV2_GEOMETRY_INDEXDATAMANAGER_H_
+
+#include <bitset>
+#include <cstddef>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include "libGLESv2/Context.h"
+
+namespace gl
+{
+
+class Buffer;
+class BufferBackEnd;
+class TranslatedIndexBuffer;
+struct FormatConverter;
+
+struct TranslatedIndexData
+{
+ GLuint minIndex;
+ GLuint maxIndex;
+ GLuint count;
+ GLuint indexSize;
+
+ TranslatedIndexBuffer *buffer;
+ GLsizei offset;
+};
+
+class IndexDataManager
+{
+ public:
+ IndexDataManager(Context *context, BufferBackEnd *backend);
+ ~IndexDataManager();
+
+ GLenum preRenderValidate(GLenum mode, GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices, TranslatedIndexData *translated);
+ GLenum preRenderValidateUnindexed(GLenum mode, GLsizei count, TranslatedIndexData *indexInfo);
+
+ private:
+ std::size_t IndexDataManager::typeSize(GLenum type) const;
+ std::size_t IndexDataManager::indexSize(GLenum type) const;
+ std::size_t spaceRequired(GLenum type, GLsizei count) const;
+ TranslatedIndexBuffer *prepareIndexBuffer(GLenum type, std::size_t requiredSpace);
+
+ Context *mContext;
+ BufferBackEnd *mBackend;
+
+ bool mIntIndicesSupported;
+
+ TranslatedIndexBuffer *mStreamBufferShort;
+ TranslatedIndexBuffer *mStreamBufferInt;
+
+ TranslatedIndexBuffer *mCountingBuffer;
+ GLsizei mCountingBufferSize;
+
+ TranslatedIndexBuffer *mLineLoopBuffer;
+};
+
+}
+
+#endif // LIBGLESV2_GEOMETRY_INDEXDATAMANAGER_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.cpp
new file mode 100644
index 0000000..7762e07
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.cpp
@@ -0,0 +1,271 @@
+//
+// 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.
+//
+
+// geometry/VertexDataManager.h: Defines the VertexDataManager, a class that
+// runs the Buffer translation process.
+
+#include "libGLESv2/geometry/VertexDataManager.h"
+
+#include <limits>
+
+#include "common/debug.h"
+
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/Program.h"
+
+#include "libGLESv2/geometry/backend.h"
+#include "libGLESv2/geometry/IndexDataManager.h"
+
+namespace
+{
+ enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 };
+}
+
+namespace gl
+{
+
+VertexDataManager::VertexDataManager(Context *context, BufferBackEnd *backend)
+ : mContext(context), mBackend(backend), mDirtyCurrentValues(true), mCurrentValueOffset(0)
+{
+ mStreamBuffer = mBackend->createVertexBuffer(INITIAL_STREAM_BUFFER_SIZE);
+ try
+ {
+ mCurrentValueBuffer = mBackend->createVertexBufferForStrideZero(4 * sizeof(float) * MAX_VERTEX_ATTRIBS);
+ }
+ catch (...)
+ {
+ delete mStreamBuffer;
+ throw;
+ }
+}
+
+VertexDataManager::~VertexDataManager()
+{
+ delete mStreamBuffer;
+ delete mCurrentValueBuffer;
+}
+
+std::bitset<MAX_VERTEX_ATTRIBS> VertexDataManager::getActiveAttribs() const
+{
+ std::bitset<MAX_VERTEX_ATTRIBS> active;
+
+ Program *program = mContext->getCurrentProgram();
+
+ for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+ {
+ active[attributeIndex] = (program->getSemanticIndex(attributeIndex) != -1);
+ }
+
+ return active;
+}
+
+GLenum VertexDataManager::preRenderValidate(GLint start, GLsizei count,
+ TranslatedAttribute *translated)
+{
+ const AttributeState *attribs = mContext->getVertexAttribBlock();
+ const std::bitset<MAX_VERTEX_ATTRIBS> activeAttribs = getActiveAttribs();
+
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (!activeAttribs[i] && attribs[i].mEnabled && attribs[i].mBoundBuffer != 0 && !mContext->getBuffer(attribs[i].mBoundBuffer))
+ return GL_INVALID_OPERATION;
+ }
+
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ translated[i].enabled = activeAttribs[i];
+ }
+
+ bool usesCurrentValues = false;
+
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (activeAttribs[i] && !attribs[i].mEnabled)
+ {
+ usesCurrentValues = true;
+ break;
+ }
+ }
+
+ // Handle the identity-mapped attributes.
+ // Process array attributes.
+
+ std::size_t requiredSpace = 0;
+
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (activeAttribs[i] && attribs[i].mEnabled)
+ {
+ requiredSpace += spaceRequired(attribs[i], count);
+ }
+ }
+
+ if (requiredSpace > mStreamBuffer->size())
+ {
+ std::size_t newSize = std::max(requiredSpace, 3 * mStreamBuffer->size() / 2); // 1.5 x mStreamBuffer->size() is arbitrary and should be checked to see we don't have too many reallocations.
+
+ TranslatedVertexBuffer *newStreamBuffer = mBackend->createVertexBuffer(newSize);
+
+ delete mStreamBuffer;
+ mStreamBuffer = newStreamBuffer;
+ }
+
+ mStreamBuffer->reserveSpace(requiredSpace);
+
+ for (size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (activeAttribs[i] && attribs[i].mEnabled)
+ {
+ FormatConverter formatConverter = mBackend->getFormatConverter(attribs[i].mType, attribs[i].mSize, attribs[i].mNormalized);
+
+ translated[i].nonArray = false;
+ translated[i].type = attribs[i].mType;
+ translated[i].size = attribs[i].mSize;
+ translated[i].normalized = attribs[i].mNormalized;
+ translated[i].stride = formatConverter.outputVertexSize;
+ translated[i].buffer = mStreamBuffer;
+
+ size_t inputStride = interpretGlStride(attribs[i]);
+ size_t elementSize = typeSize(attribs[i].mType) * attribs[i].mSize;
+
+ void *output = mStreamBuffer->map(spaceRequired(attribs[i], count), &translated[i].offset);
+
+ const void *input;
+ if (attribs[i].mBoundBuffer)
+ {
+ Buffer *buffer = mContext->getBuffer(attribs[i].mBoundBuffer);
+
+ size_t offset = reinterpret_cast<size_t>(attribs[i].mPointer);
+
+ // Before we calculate the required size below, make sure it can be computed without integer overflow.
+ if (std::numeric_limits<std::size_t>::max() - start < static_cast<std::size_t>(count)
+ || std::numeric_limits<std::size_t>::max() / inputStride < static_cast<std::size_t>(start + count - 1) // it's a prerequisite that count >= 1, so start+count-1 >= 0.
+ || std::numeric_limits<std::size_t>::max() - offset < inputStride * (start + count - 1)
+ || std::numeric_limits<std::size_t>::max() - elementSize < offset + inputStride * (start + count - 1) + elementSize)
+ {
+ mStreamBuffer->unmap();
+ return GL_INVALID_OPERATION;
+ }
+
+ if (offset + inputStride * (start + count - 1) + elementSize > buffer->size())
+ {
+ mStreamBuffer->unmap();
+ return GL_INVALID_OPERATION;
+ }
+
+ input = static_cast<const char*>(buffer->data()) + offset;
+ }
+ else
+ {
+ input = attribs[i].mPointer;
+ }
+
+ input = static_cast<const char*>(input) + inputStride * start;
+
+ if (formatConverter.identity && inputStride == elementSize)
+ {
+ memcpy(output, input, count * inputStride);
+ }
+ else
+ {
+ formatConverter.convertArray(input, inputStride, count, output);
+ }
+
+ mStreamBuffer->unmap();
+ }
+ }
+
+ if (usesCurrentValues)
+ {
+ processNonArrayAttributes(attribs, activeAttribs, translated, count);
+ }
+
+ return GL_NO_ERROR;
+}
+
+std::size_t VertexDataManager::typeSize(GLenum type) const
+{
+ switch (type)
+ {
+ case GL_BYTE: case GL_UNSIGNED_BYTE: return sizeof(GLbyte);
+ case GL_SHORT: case GL_UNSIGNED_SHORT: return sizeof(GLshort);
+ case GL_FIXED: return sizeof(GLfixed);
+ case GL_FLOAT: return sizeof(GLfloat);
+ default: UNREACHABLE(); return sizeof(GLfloat);
+ }
+}
+
+std::size_t VertexDataManager::interpretGlStride(const AttributeState &attrib) const
+{
+ return attrib.mStride ? attrib.mStride : typeSize(attrib.mType) * attrib.mSize;
+}
+
+// Round up x (>=0) to the next multiple of multiple (>0).
+// 0 rounds up to 0.
+std::size_t VertexDataManager::roundUp(std::size_t x, std::size_t multiple) const
+{
+ ASSERT(x >= 0);
+ ASSERT(multiple > 0);
+
+ std::size_t remainder = x % multiple;
+ if (remainder != 0)
+ {
+ return x + multiple - remainder;
+ }
+ else
+ {
+ return x;
+ }
+}
+
+std::size_t VertexDataManager::spaceRequired(const AttributeState &attrib, std::size_t maxVertex) const
+{
+ std::size_t size = mBackend->getFormatConverter(attrib.mType, attrib.mSize, attrib.mNormalized).outputVertexSize;
+ size *= maxVertex;
+
+ return roundUp(size, 4 * sizeof(GLfloat));
+}
+
+void VertexDataManager::processNonArrayAttributes(const AttributeState *attribs, const std::bitset<MAX_VERTEX_ATTRIBS> &activeAttribs, TranslatedAttribute *translated, std::size_t count)
+{
+ if (mDirtyCurrentValues)
+ {
+ std::size_t totalSize = 4 * sizeof(float) * MAX_VERTEX_ATTRIBS;
+
+ mCurrentValueBuffer->reserveSpace(totalSize);
+
+ float* currentValues = static_cast<float*>(mCurrentValueBuffer->map(totalSize, &mCurrentValueOffset));
+
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ // This assumes that the GL_FLOATx4 is supported by the back-end. (For D3D9, it is a mandatory format.)
+ currentValues[i*4+0] = attribs[i].mCurrentValue[0];
+ currentValues[i*4+1] = attribs[i].mCurrentValue[1];
+ currentValues[i*4+2] = attribs[i].mCurrentValue[2];
+ currentValues[i*4+3] = attribs[i].mCurrentValue[3];
+ }
+
+ mCurrentValueBuffer->unmap();
+ }
+
+ for (std::size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (activeAttribs[i] && !attribs[i].mEnabled)
+ {
+ translated[i].nonArray = true;
+
+ translated[i].buffer = mCurrentValueBuffer;
+
+ translated[i].type = GL_FLOAT;
+ translated[i].size = 4;
+ translated[i].normalized = false;
+ translated[i].stride = 0;
+ translated[i].offset = mCurrentValueOffset + 4 * sizeof(float) * i;
+ }
+ }
+}
+
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.h b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.h
new file mode 100644
index 0000000..04900b8
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.h
@@ -0,0 +1,66 @@
+//
+// 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.
+//
+
+// geometry/VertexDataManager.h: Defines the VertexDataManager, a class that
+// runs the Buffer translation process.
+
+#ifndef LIBGLESV2_GEOMETRY_VERTEXDATAMANAGER_H_
+#define LIBGLESV2_GEOMETRY_VERTEXDATAMANAGER_H_
+
+#include <bitset>
+#include <cstddef>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include "libGLESv2/Context.h"
+
+namespace gl
+{
+
+class Buffer;
+class BufferBackEnd;
+class TranslatedVertexBuffer;
+struct TranslatedAttribute;
+struct FormatConverter;
+struct TranslatedIndexData;
+
+class VertexDataManager
+{
+ public:
+ VertexDataManager(Context *context, BufferBackEnd *backend);
+ ~VertexDataManager();
+
+ void dirtyCurrentValues() { mDirtyCurrentValues = true; }
+
+ GLenum preRenderValidate(GLint start,
+ GLsizei count,
+ TranslatedAttribute *outAttribs);
+
+ private:
+ std::bitset<MAX_VERTEX_ATTRIBS> getActiveAttribs() const;
+
+ void processNonArrayAttributes(const AttributeState *attribs, const std::bitset<MAX_VERTEX_ATTRIBS> &activeAttribs, TranslatedAttribute *translated, std::size_t count);
+
+ std::size_t typeSize(GLenum type) const;
+ std::size_t interpretGlStride(const AttributeState &attrib) const;
+
+ std::size_t roundUp(std::size_t x, std::size_t multiple) const;
+ std::size_t spaceRequired(const AttributeState &attrib, std::size_t maxVertex) const;
+
+ Context *mContext;
+ BufferBackEnd *mBackend;
+
+ TranslatedVertexBuffer *mStreamBuffer;
+
+ bool mDirtyCurrentValues;
+ std::size_t mCurrentValueOffset; // Offset within mCurrentValueBuffer that the current attribute values were last loaded at.
+ TranslatedVertexBuffer *mCurrentValueBuffer;
+};
+
+}
+
+#endif // LIBGLESV2_GEOMETRY_VERTEXDATAMANAGER_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/backend.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/backend.cpp
new file mode 100644
index 0000000..3f5e283
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/backend.cpp
@@ -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.
+//
+
+// geometry/backend.h: Abstract classes BufferBackEnd, TranslatedVertexBuffer and TranslatedIndexBuffer
+// that must be implemented by any API-specific implementation of ANGLE.
+
+#include "libGLESv2/geometry/backend.h"
+
+#include "common/debug.h"
+
+namespace gl
+{
+
+void *TranslatedBuffer::map(std::size_t requiredSpace, std::size_t *offset)
+{
+ ASSERT(requiredSpace <= mBufferSize);
+
+ reserveSpace(requiredSpace);
+
+ *offset = mCurrentPoint;
+ mCurrentPoint += requiredSpace;
+
+ return streamingMap(*offset, requiredSpace);
+}
+
+void TranslatedBuffer::reserveSpace(std::size_t requiredSpace)
+{
+ if (mCurrentPoint + requiredSpace > mBufferSize)
+ {
+ recycle();
+ mCurrentPoint = 0;
+ }
+}
+
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/backend.h b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/backend.h
new file mode 100644
index 0000000..d18a908
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/backend.h
@@ -0,0 +1,110 @@
+//
+// 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.
+//
+
+// geometry/backend.h: Abstract classes BufferBackEnd, TranslatedVertexBuffer and TranslatedIndexBuffer
+// that must be implemented by any API-specific implementation of ANGLE.
+
+#ifndef LIBGLESV2_GEOMETRY_BACKEND_H_
+#define LIBGLESV2_GEOMETRY_BACKEND_H_
+
+#include <cstddef>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include "libGLESv2/Context.h"
+
+namespace gl
+{
+class TranslatedVertexBuffer;
+class TranslatedIndexBuffer;
+
+struct FormatConverter
+{
+ bool identity;
+ std::size_t outputVertexSize;
+ void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out);
+};
+
+struct TranslatedAttribute
+{
+ bool enabled;
+ bool nonArray;
+
+ // These are the original untranslated values. (Or just have some sort of BufferBackEnd::TranslatedTypeKey.)
+ GLenum type;
+ std::size_t size;
+ bool normalized;
+
+ std::size_t offset;
+
+ std::size_t stride; // 0 means not to advance the read pointer at all
+
+ std::size_t semanticIndex;
+
+ TranslatedVertexBuffer *buffer;
+};
+
+class BufferBackEnd
+{
+ public:
+ virtual ~BufferBackEnd() { }
+
+ virtual bool supportIntIndices() = 0;
+
+ virtual TranslatedVertexBuffer *createVertexBuffer(std::size_t size) = 0;
+ virtual TranslatedVertexBuffer *createVertexBufferForStrideZero(std::size_t size) = 0;
+ virtual TranslatedIndexBuffer *createIndexBuffer(std::size_t size, GLenum type) = 0;
+ virtual FormatConverter getFormatConverter(GLenum type, std::size_t size, bool normalize) = 0;
+
+ // For an identity-mappable stream, verify that the stride and offset are okay.
+ virtual bool validateStream(GLenum type, std::size_t size, std::size_t stride, std::size_t offset) const = 0;
+
+ virtual GLenum setupIndicesPreDraw(const TranslatedIndexData &indexInfo) = 0;
+ virtual GLenum setupAttributesPreDraw(const TranslatedAttribute *attributes) = 0;
+};
+
+class TranslatedBuffer
+{
+ public:
+ explicit TranslatedBuffer(std::size_t size) : mBufferSize(size), mCurrentPoint(0) { }
+ virtual ~TranslatedBuffer() { }
+
+ std::size_t size() const { return mBufferSize; }
+
+ virtual void *map() = 0;
+ virtual void unmap() = 0;
+
+ void reserveSpace(std::size_t requiredSpace);
+
+ void *map(std::size_t requiredSpace, std::size_t *offset);
+
+ protected:
+ virtual void recycle() = 0;
+ virtual void *streamingMap(std::size_t offset, std::size_t size) = 0;
+
+ private:
+ std::size_t mBufferSize;
+ std::size_t mCurrentPoint;
+
+ DISALLOW_COPY_AND_ASSIGN(TranslatedBuffer);
+};
+
+class TranslatedVertexBuffer : public TranslatedBuffer
+{
+ public:
+ explicit TranslatedVertexBuffer(std::size_t size) : TranslatedBuffer(size) { }
+};
+
+class TranslatedIndexBuffer : public TranslatedBuffer
+{
+ public:
+ explicit TranslatedIndexBuffer(std::size_t size) : TranslatedBuffer(size) { }
+};
+
+}
+
+#endif // LIBGLESV2_GEOMETRY_BACKEND_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/dx9.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/dx9.cpp
new file mode 100644
index 0000000..e51befb
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/dx9.cpp
@@ -0,0 +1,613 @@
+//
+// 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.
+//
+
+// geometry/dx9.h: Direct3D 9-based implementation of BufferBackEnd, TranslatedVertexBuffer and TranslatedIndexBuffer.
+
+#include "libGLESv2/geometry/dx9.h"
+
+#include <cstddef>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include "common/debug.h"
+
+#include "libGLESv2/Context.h"
+#include "libGLESv2/main.h"
+#include "libGLESv2/geometry/vertexconversion.h"
+#include "libGLESv2/geometry/IndexDataManager.h"
+
+namespace
+{
+// 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<GLuint, 16> { };
+template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : gl::FixedToFloat<GLuint, 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 };
+};
+
+}
+
+namespace gl
+{
+Dx9BackEnd::Dx9BackEnd(Context *context, IDirect3DDevice9 *d3ddevice)
+ : mDevice(d3ddevice)
+{
+ mDevice->AddRef();
+
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
+ {
+ mAppliedAttribEnabled[i] = true;
+ mStreamFrequency[i] = STREAM_FREQUENCY_UNINSTANCED;
+ }
+
+ mStreamFrequency[MAX_VERTEX_ATTRIBS] = STREAM_FREQUENCY_UNINSTANCED;
+
+ D3DCAPS9 caps = context->getDeviceCaps();
+
+ IDirect3D9 *d3dObject;
+ mDevice->GetDirect3D(&d3dObject);
+
+ D3DADAPTER_IDENTIFIER9 ident;
+ d3dObject->GetAdapterIdentifier(caps.AdapterOrdinal, 0, &ident);
+ d3dObject->Release();
+
+ // Instancing is mandatory for all HW with SM3 vertex shaders, but avoid hardware where it does not work.
+ mUseInstancingForStrideZero = (caps.VertexShaderVersion >= D3DVS_VERSION(3, 0) && ident.VendorId != 0x8086);
+ mSupportIntIndices = (caps.MaxVertexIndex >= (1 << 16));
+
+ checkVertexCaps(caps.DeclTypes);
+}
+
+Dx9BackEnd::~Dx9BackEnd()
+{
+ mDevice->Release();
+}
+
+bool Dx9BackEnd::supportIntIndices()
+{
+ return mSupportIntIndices;
+}
+
+// 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) }, \
+ }
+
+const Dx9BackEnd::TranslationDescription Dx9BackEnd::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(GL_FIXED),
+ TRANSLATIONS_FOR_TYPE(GL_FLOAT)
+};
+
+void Dx9BackEnd::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;
+ }
+ }
+ }
+ }
+}
+
+TranslatedVertexBuffer *Dx9BackEnd::createVertexBuffer(std::size_t size)
+{
+ return new Dx9VertexBuffer(mDevice, size);
+}
+
+TranslatedVertexBuffer *Dx9BackEnd::createVertexBufferForStrideZero(std::size_t size)
+{
+ if (mUseInstancingForStrideZero)
+ {
+ return new Dx9VertexBuffer(mDevice, size);
+ }
+ else
+ {
+ return new Dx9VertexBufferZeroStrideWorkaround(mDevice, size);
+ }
+}
+
+TranslatedIndexBuffer *Dx9BackEnd::createIndexBuffer(std::size_t size, GLenum type)
+{
+ return new Dx9IndexBuffer(mDevice, size, type);
+}
+
+// This is used to index mAttributeTypes and mPossibleTranslations.
+unsigned int Dx9BackEnd::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;
+ }
+}
+
+FormatConverter Dx9BackEnd::getFormatConverter(GLenum type, std::size_t size, bool normalize)
+{
+ return mAttributeTypes[typeIndex(type)][normalize][size-1].formatConverter;
+}
+
+D3DDECLTYPE Dx9BackEnd::mapAttributeType(GLenum type, std::size_t size, bool normalize) const
+{
+ return mAttributeTypes[typeIndex(type)][normalize][size-1].d3dDeclType;
+}
+
+bool Dx9BackEnd::validateStream(GLenum type, std::size_t size, std::size_t stride, std::size_t offset) const
+{
+ // D3D9 requires the stream offset and stride to be a multiple of DWORD.
+ return (stride % sizeof(DWORD) == 0 && offset % sizeof(DWORD) == 0);
+}
+
+IDirect3DVertexBuffer9 *Dx9BackEnd::getDxBuffer(TranslatedVertexBuffer *vb) const
+{
+ return vb ? static_cast<Dx9VertexBuffer*>(vb)->getBuffer() : NULL;
+}
+
+IDirect3DIndexBuffer9 *Dx9BackEnd::getDxBuffer(TranslatedIndexBuffer *ib) const
+{
+ return ib ? static_cast<Dx9IndexBuffer*>(ib)->getBuffer() : NULL;
+}
+
+GLenum Dx9BackEnd::setupIndicesPreDraw(const TranslatedIndexData &indexInfo)
+{
+ mDevice->SetIndices(getDxBuffer(indexInfo.buffer));
+ return GL_NO_ERROR;
+}
+
+GLenum Dx9BackEnd::setupAttributesPreDraw(const TranslatedAttribute *attributes)
+{
+ HRESULT hr;
+
+ D3DVERTEXELEMENT9 elements[MAX_VERTEX_ATTRIBS+1];
+
+ D3DVERTEXELEMENT9 *nextElement = &elements[0];
+
+ for (BYTE i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (attributes[i].enabled)
+ {
+ nextElement->Stream = i + 1; // Stream 0 is skipped because D3D does not permit it to be an instanced stream.
+ nextElement->Offset = 0;
+ nextElement->Type = static_cast<BYTE>(mapAttributeType(attributes[i].type, attributes[i].size, attributes[i].normalized));
+ nextElement->Method = D3DDECLMETHOD_DEFAULT;
+ nextElement->Usage = D3DDECLUSAGE_TEXCOORD;
+ nextElement->UsageIndex = attributes[i].semanticIndex;
+ nextElement++;
+ }
+ }
+
+ static const D3DVERTEXELEMENT9 end = D3DDECL_END();
+ *nextElement = end;
+
+ IDirect3DVertexDeclaration9* vertexDeclaration;
+ hr = mDevice->CreateVertexDeclaration(elements, &vertexDeclaration);
+ mDevice->SetVertexDeclaration(vertexDeclaration);
+ vertexDeclaration->Release();
+
+ mDevice->SetStreamSource(0, NULL, 0, 0);
+
+ bool nonArrayAttributes = false;
+
+ for (size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (attributes[i].enabled)
+ {
+ if (attributes[i].nonArray) nonArrayAttributes = true;
+
+ mDevice->SetStreamSource(i + 1, getDxBuffer(attributes[i].buffer), attributes[i].offset, attributes[i].stride);
+ if (!mAppliedAttribEnabled[i])
+ {
+ mAppliedAttribEnabled[i] = true;
+ }
+ }
+ else
+ {
+ if (mAppliedAttribEnabled[i])
+ {
+ mDevice->SetStreamSource(i + 1, 0, 0, 0);
+ mAppliedAttribEnabled[i] = false;
+ }
+ }
+ }
+
+ if (mUseInstancingForStrideZero)
+ {
+ // When there are no stride zero attributes, we disable instancing so that DrawPrimitive can be used.
+
+ if (nonArrayAttributes)
+ {
+ if (mStreamFrequency[0] != STREAM_FREQUENCY_INDEXED)
+ {
+ mStreamFrequency[0] = STREAM_FREQUENCY_INDEXED;
+ mDevice->SetStreamSourceFreq(0, D3DSTREAMSOURCE_INDEXEDDATA | 1);
+ }
+
+ for (size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (attributes[i].enabled)
+ {
+ if (attributes[i].nonArray)
+ {
+ if (mStreamFrequency[i+1] != STREAM_FREQUENCY_INSTANCED)
+ {
+ mStreamFrequency[i+1] = STREAM_FREQUENCY_INSTANCED;
+ mDevice->SetStreamSourceFreq(i + 1, D3DSTREAMSOURCE_INSTANCEDATA | 1);
+ }
+ }
+ else
+ {
+ if (mStreamFrequency[i+1] != STREAM_FREQUENCY_INDEXED)
+ {
+ mStreamFrequency[i+1] = STREAM_FREQUENCY_INDEXED;
+ mDevice->SetStreamSourceFreq(i + 1, D3DSTREAMSOURCE_INDEXEDDATA | 1);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ for (size_t i = 0; i < MAX_VERTEX_ATTRIBS + 1; i++)
+ {
+ if (mStreamFrequency[i] != STREAM_FREQUENCY_UNINSTANCED)
+ {
+ mStreamFrequency[i] = STREAM_FREQUENCY_UNINSTANCED;
+
+ // This should not be needed, but otherwise there is a buggy driver that will leave instancing
+ // enabled for the first draw after it has been turned off.
+ mDevice->SetStreamSourceFreq(i, D3DSTREAMSOURCE_INDEXEDDATA | 1);
+
+ mDevice->SetStreamSourceFreq(i, 1);
+ }
+ }
+ }
+ }
+
+ return GL_NO_ERROR;
+}
+
+Dx9BackEnd::Dx9VertexBuffer::Dx9VertexBuffer(IDirect3DDevice9 *device, std::size_t size)
+ : TranslatedVertexBuffer(size)
+{
+ HRESULT hr = device->CreateVertexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mVertexBuffer, NULL);
+ if (hr != S_OK)
+ {
+ ERR("Out of memory allocating a vertex buffer of size %lu.", size);
+ throw std::bad_alloc();
+ }
+}
+
+Dx9BackEnd::Dx9VertexBuffer::Dx9VertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags)
+ : TranslatedVertexBuffer(size)
+{
+ HRESULT hr = device->CreateVertexBuffer(size, usageFlags, 0, D3DPOOL_DEFAULT, &mVertexBuffer, NULL);
+ if (hr != S_OK)
+ {
+ ERR("Out of memory allocating a vertex buffer of size %lu.", size);
+ throw std::bad_alloc();
+ }
+}
+
+
+Dx9BackEnd::Dx9VertexBuffer::~Dx9VertexBuffer()
+{
+ mVertexBuffer->Release();
+}
+
+IDirect3DVertexBuffer9 *Dx9BackEnd::Dx9VertexBuffer::getBuffer() const
+{
+ return mVertexBuffer;
+}
+
+void *Dx9BackEnd::Dx9VertexBuffer::map()
+{
+ void *mapPtr;
+
+ mVertexBuffer->Lock(0, 0, &mapPtr, 0);
+
+ return mapPtr;
+}
+
+void Dx9BackEnd::Dx9VertexBuffer::unmap()
+{
+ mVertexBuffer->Unlock();
+}
+
+void Dx9BackEnd::Dx9VertexBuffer::recycle()
+{
+ void *dummy;
+ mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
+ mVertexBuffer->Unlock();
+}
+
+void *Dx9BackEnd::Dx9VertexBuffer::streamingMap(std::size_t offset, std::size_t size)
+{
+ void *mapPtr;
+
+ mVertexBuffer->Lock(offset, size, &mapPtr, D3DLOCK_NOOVERWRITE);
+
+ return mapPtr;
+}
+
+// Normally VBs are created with D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, but some hardware & drivers won't render
+// if any stride-zero streams are in D3DUSAGE_DYNAMIC VBs, so this provides a way to create such VBs with only D3DUSAGE_WRITEONLY set.
+// D3DLOCK_DISCARD and D3DLOCK_NOOVERWRITE are only available on D3DUSAGE_DYNAMIC VBs, so we override methods to avoid using these flags.
+Dx9BackEnd::Dx9VertexBufferZeroStrideWorkaround::Dx9VertexBufferZeroStrideWorkaround(IDirect3DDevice9 *device, std::size_t size)
+ : Dx9VertexBuffer(device, size, D3DUSAGE_WRITEONLY)
+{
+}
+
+void Dx9BackEnd::Dx9VertexBufferZeroStrideWorkaround::recycle()
+{
+}
+
+void *Dx9BackEnd::Dx9VertexBufferZeroStrideWorkaround::streamingMap(std::size_t offset, std::size_t size)
+{
+ void *mapPtr;
+
+ getBuffer()->Lock(offset, size, &mapPtr, 0);
+
+ return mapPtr;
+}
+
+Dx9BackEnd::Dx9IndexBuffer::Dx9IndexBuffer(IDirect3DDevice9 *device, std::size_t size, GLenum type)
+ : TranslatedIndexBuffer(size)
+{
+ ASSERT(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT);
+
+ D3DFORMAT format = (type == GL_UNSIGNED_SHORT) ? D3DFMT_INDEX16 : D3DFMT_INDEX32;
+
+ HRESULT hr = device->CreateIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, D3DPOOL_DEFAULT, &mIndexBuffer, NULL);
+ if (hr != S_OK)
+ {
+ ERR("Out of memory allocating an index buffer of size %lu.", size);
+ throw std::bad_alloc();
+ }
+}
+
+Dx9BackEnd::Dx9IndexBuffer::~Dx9IndexBuffer()
+{
+ mIndexBuffer->Release();
+}
+
+IDirect3DIndexBuffer9*Dx9BackEnd::Dx9IndexBuffer::getBuffer() const
+{
+ return mIndexBuffer;
+}
+
+void *Dx9BackEnd::Dx9IndexBuffer::map()
+{
+ void *mapPtr;
+
+ mIndexBuffer->Lock(0, 0, &mapPtr, 0);
+
+ return mapPtr;
+}
+
+void Dx9BackEnd::Dx9IndexBuffer::unmap()
+{
+ mIndexBuffer->Unlock();
+}
+
+void Dx9BackEnd::Dx9IndexBuffer::recycle()
+{
+ void *dummy;
+ mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
+ mIndexBuffer->Unlock();
+}
+
+void *Dx9BackEnd::Dx9IndexBuffer::streamingMap(std::size_t offset, std::size_t size)
+{
+ void *mapPtr;
+
+ mIndexBuffer->Lock(offset, size, &mapPtr, D3DLOCK_NOOVERWRITE);
+
+ return mapPtr;
+}
+
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/dx9.h b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/dx9.h
new file mode 100644
index 0000000..6068dd6
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/dx9.h
@@ -0,0 +1,137 @@
+//
+// 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.
+//
+
+// geometry/dx9.h: Direct3D 9-based implementation of BufferBackEnd, TranslatedVertexBuffer and TranslatedIndexBuffer.
+
+#ifndef LIBGLESV2_GEOMETRY_DX9_H_
+#define LIBGLESV2_GEOMETRY_DX9_H_
+
+#include <d3d9.h>
+
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/geometry/backend.h"
+
+namespace gl
+{
+
+class Dx9BackEnd : public BufferBackEnd
+{
+ public:
+ explicit Dx9BackEnd(Context *context, IDirect3DDevice9 *d3ddevice);
+ ~Dx9BackEnd();
+
+ virtual bool supportIntIndices();
+
+ virtual TranslatedVertexBuffer *createVertexBuffer(std::size_t size);
+ virtual TranslatedVertexBuffer *createVertexBufferForStrideZero(std::size_t size);
+ virtual TranslatedIndexBuffer *createIndexBuffer(std::size_t size, GLenum type);
+ virtual FormatConverter getFormatConverter(GLenum type, std::size_t size, bool normalize);
+
+ virtual bool validateStream(GLenum type, std::size_t size, std::size_t stride, std::size_t offset) const;
+
+ virtual GLenum setupIndicesPreDraw(const TranslatedIndexData &indexInfo);
+ virtual GLenum setupAttributesPreDraw(const TranslatedAttribute *attributes);
+
+ private:
+ IDirect3DDevice9 *mDevice;
+
+ bool mUseInstancingForStrideZero;
+ bool mSupportIntIndices;
+
+ bool mAppliedAttribEnabled[MAX_VERTEX_ATTRIBS];
+
+ enum StreamFrequency
+ {
+ STREAM_FREQUENCY_UNINSTANCED = 0,
+ STREAM_FREQUENCY_INDEXED,
+ STREAM_FREQUENCY_INSTANCED
+ };
+
+ StreamFrequency mStreamFrequency[MAX_VERTEX_ATTRIBS+1];
+
+ struct TranslationInfo
+ {
+ FormatConverter formatConverter;
+ D3DDECLTYPE d3dDeclType;
+ };
+
+ enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 };
+
+ TranslationInfo mAttributeTypes[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size-1]
+
+ struct TranslationDescription
+ {
+ DWORD capsFlag;
+ TranslationInfo preferredConversion;
+ TranslationInfo 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;
+
+ class Dx9VertexBuffer : public TranslatedVertexBuffer
+ {
+ public:
+ Dx9VertexBuffer(IDirect3DDevice9 *device, std::size_t size);
+ virtual ~Dx9VertexBuffer();
+
+ IDirect3DVertexBuffer9 *getBuffer() const;
+
+ protected:
+ Dx9VertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags);
+
+ virtual void *map();
+ virtual void unmap();
+
+ virtual void recycle();
+ virtual void *streamingMap(std::size_t offset, std::size_t size);
+
+ private:
+ IDirect3DVertexBuffer9 *mVertexBuffer;
+ };
+
+ class Dx9VertexBufferZeroStrideWorkaround : public Dx9VertexBuffer
+ {
+ public:
+ Dx9VertexBufferZeroStrideWorkaround(IDirect3DDevice9 *device, std::size_t size);
+
+ protected:
+ virtual void recycle();
+ virtual void *streamingMap(std::size_t offset, std::size_t size);
+ };
+
+ class Dx9IndexBuffer : public TranslatedIndexBuffer
+ {
+ public:
+ Dx9IndexBuffer(IDirect3DDevice9 *device, std::size_t size, GLenum type);
+ virtual ~Dx9IndexBuffer();
+
+ IDirect3DIndexBuffer9 *getBuffer() const;
+
+ protected:
+ virtual void *map();
+ virtual void unmap();
+
+ virtual void recycle();
+ virtual void *streamingMap(std::size_t offset, std::size_t size);
+
+ private:
+ IDirect3DIndexBuffer9 *mIndexBuffer;
+ };
+
+ IDirect3DVertexBuffer9 *getDxBuffer(TranslatedVertexBuffer *vb) const;
+ IDirect3DIndexBuffer9 *getDxBuffer(TranslatedIndexBuffer *ib) const;
+
+ D3DDECLTYPE mapAttributeType(GLenum type, std::size_t size, bool normalized) const;
+};
+
+}
+
+#endif // LIBGLESV2_GEOMETRY_DX9_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/vertexconversion.h b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/vertexconversion.h
new file mode 100644
index 0000000..e55dc72
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/vertexconversion.h
@@ -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.
+//
+
+// geometry/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_GEOMETRY_VERTEXCONVERSION_H_
+#define LIBGLESV2_GEOMETRY_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_GEOMETRY_VERTEXCONVERSION_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.cpp
new file mode 100644
index 0000000..25d083b
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.cpp
@@ -0,0 +1,5451 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions.
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <exception>
+#include <limits>
+
+#include "common/debug.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/utilities.h"
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/Context.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/Program.h"
+#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/Shader.h"
+#include "libGLESv2/Texture.h"
+
+extern "C"
+{
+
+void __stdcall glActiveTexture(GLenum texture)
+{
+ TRACE("(GLenum texture = 0x%X)", texture);
+
+ try
+ {
+ if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + gl::MAX_TEXTURE_IMAGE_UNITS - 1)
+ {
+ return error(GL_INVALID_ENUM);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->setActiveSampler(texture - GL_TEXTURE0);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glAttachShader(GLuint program, GLuint shader)
+{
+ TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *programObject = context->getProgram(program);
+ gl::Shader *shaderObject = context->getShader(shader);
+
+ if (!programObject)
+ {
+ 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 glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
+{
+ TRACE("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name);
+
+ try
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ }
+
+ if (strncmp(name, "gl_", 3) == 0)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ programObject->bindAttributeLocation(index, name);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glBindBuffer(GLenum target, GLuint buffer)
+{
+ TRACE("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ switch (target)
+ {
+ case GL_ARRAY_BUFFER:
+ context->bindArrayBuffer(buffer);
+ return;
+ case GL_ELEMENT_ARRAY_BUFFER:
+ context->bindElementArrayBuffer(buffer);
+ return;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer)
+{
+ TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
+
+ try
+ {
+ if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
+ {
+ return error(GL_INVALID_ENUM);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
+ {
+ context->bindReadFramebuffer(framebuffer);
+ }
+
+ if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
+ {
+ context->bindDrawFramebuffer(framebuffer);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer)
+{
+ TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
+
+ try
+ {
+ if (target != GL_RENDERBUFFER)
+ {
+ return error(GL_INVALID_ENUM);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->bindRenderbuffer(renderbuffer);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glBindTexture(GLenum target, GLuint texture)
+{
+ TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Texture *textureObject = context->getTexture(texture);
+
+ if (textureObject && textureObject->getTarget() != target && texture != 0)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ context->bindTexture2D(texture);
+ return;
+ case GL_TEXTURE_CUBE_MAP:
+ context->bindTextureCubeMap(texture);
+ return;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+ TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
+ red, green, blue, alpha);
+
+ try
+ {
+ gl::Context* context = gl::getContext();
+
+ if (context)
+ {
+ context->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)
+{
+ TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
+
+ try
+ {
+ switch (modeRGB)
+ {
+ case GL_FUNC_ADD:
+ case GL_FUNC_SUBTRACT:
+ case GL_FUNC_REVERSE_SUBTRACT:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ switch (modeAlpha)
+ {
+ case GL_FUNC_ADD:
+ case GL_FUNC_SUBTRACT:
+ case GL_FUNC_REVERSE_SUBTRACT:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->setBlendEquation(modeRGB, modeAlpha);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glBlendFunc(GLenum sfactor, GLenum dfactor)
+{
+ glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
+}
+
+void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+{
+ TRACE("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
+ srcRGB, dstRGB, srcAlpha, dstAlpha);
+
+ try
+ {
+ switch (srcRGB)
+ {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ case GL_SRC_ALPHA_SATURATE:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ switch (dstRGB)
+ {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ switch (srcAlpha)
+ {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ case GL_SRC_ALPHA_SATURATE:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ switch (dstAlpha)
+ {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ 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::getContext();
+
+ 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)
+{
+ TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)",
+ target, size, data, usage);
+
+ try
+ {
+ if (size < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ switch (usage)
+ {
+ case GL_STREAM_DRAW:
+ case GL_STATIC_DRAW:
+ case GL_DYNAMIC_DRAW:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Buffer *buffer;
+
+ switch (target)
+ {
+ case GL_ARRAY_BUFFER:
+ buffer = context->getArrayBuffer();
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER:
+ buffer = context->getElementArrayBuffer();
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (!buffer)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ buffer->bufferData(data, size, usage);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
+{
+ TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)",
+ target, offset, size, data);
+
+ try
+ {
+ if (size < 0 || offset < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (data == NULL)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Buffer *buffer;
+
+ switch (target)
+ {
+ case GL_ARRAY_BUFFER:
+ buffer = context->getArrayBuffer();
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER:
+ buffer = context->getElementArrayBuffer();
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (!buffer)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if ((size_t)size + offset > buffer->size())
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ buffer->bufferSubData(data, size, offset);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+GLenum __stdcall glCheckFramebufferStatus(GLenum target)
+{
+ TRACE("(GLenum target = 0x%X)", target);
+
+ try
+ {
+ if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
+ {
+ return error(GL_INVALID_ENUM, 0);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Framebuffer *framebuffer = NULL;
+ if (target == GL_READ_FRAMEBUFFER_ANGLE)
+ {
+ framebuffer = context->getReadFramebuffer();
+ }
+ else
+ {
+ framebuffer = context->getDrawFramebuffer();
+ }
+
+ return framebuffer->completeness();
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY, 0);
+ }
+
+ return 0;
+}
+
+void __stdcall glClear(GLbitfield mask)
+{
+ TRACE("(GLbitfield mask = %X)", mask);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->clear(mask);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+ TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
+ red, green, blue, alpha);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->setClearColor(red, green, blue, alpha);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glClearDepthf(GLclampf depth)
+{
+ TRACE("(GLclampf depth = %f)", depth);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->setClearDepth(depth);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glClearStencil(GLint s)
+{
+ TRACE("(GLint s = %d)", s);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->setClearStencil(s);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+{
+ TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
+ red, green, blue, alpha);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->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)
+{
+ TRACE("(GLuint shader = %d)", shader);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Shader *shaderObject = context->getShader(shader);
+
+ if (!shaderObject)
+ {
+ if (context->getProgram(shader))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ }
+
+ shaderObject->compile();
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
+ GLint border, GLsizei imageSize, const GLvoid* data)
+{
+ TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
+ "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
+ target, level, internalformat, width, height, border, imageSize, data);
+
+ try
+ {
+ if (level < 0 || level > gl::MAX_TEXTURE_LEVELS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (width < 0 || height < 0 || (level > 0 && !gl::isPow2(width)) || (level > 0 && !gl::isPow2(height)) || border != 0 || imageSize < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ if (width > (gl::MAX_TEXTURE_SIZE >> level) || height > (gl::MAX_TEXTURE_SIZE >> level))
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ if (width != height)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (width > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level) || height > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level))
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ switch (internalformat)
+ {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (border != 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (!context->supportsCompressedTextures())
+ {
+ return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+ }
+
+ if (imageSize != gl::ComputeCompressedSize(width, height, internalformat))
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (target == GL_TEXTURE_2D)
+ {
+ gl::Texture2D *texture = context->getTexture2D();
+
+ if (!texture)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
+ }
+ else
+ {
+ gl::TextureCubeMap *texture = context->getTextureCubeMap();
+
+ if (!texture)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ switch (target)
+ {
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
+ break;
+ default: UNREACHABLE();
+ }
+ }
+ }
+
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ GLenum format, GLsizei imageSize, const GLvoid* data)
+{
+ TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+ "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
+ "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
+ target, level, xoffset, yoffset, width, height, format, imageSize, data);
+
+ try
+ {
+ if (!gl::IsTextureTarget(target))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (level < 0 || level > gl::MAX_TEXTURE_LEVELS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0 ||
+ (level > 0 && !gl::isPow2(width)) || (level > 0 && !gl::isPow2(height)) || imageSize < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ switch (format)
+ {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (width == 0 || height == 0 || data == NULL)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (!context->supportsCompressedTextures())
+ {
+ return error(GL_INVALID_ENUM); // in this case, it's as though the format switch has failed.
+ }
+
+ 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 DXT1 textures are supported.
+ }
+
+ if (target == GL_TEXTURE_2D)
+ {
+ gl::Texture2D *texture = context->getTexture2D();
+
+ if (!texture)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if ((width % 4 != 0 && width != texture->getWidth()) ||
+ (height % 4 != 0 && height != texture->getHeight()))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
+ }
+ else if (gl::IsCubemapTextureTarget(target))
+ {
+ gl::TextureCubeMap *texture = context->getTextureCubeMap();
+
+ if (!texture)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if ((width % 4 != 0 && width != texture->getWidth()) ||
+ (height % 4 != 0 && height != texture->getHeight()))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ 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)
+{
+ TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
+ "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
+ target, level, internalformat, x, y, width, height, border);
+
+ try
+ {
+ if (level < 0 || width < 0 || height < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (level > 0 && (!gl::isPow2(width) || !gl::isPow2(height)))
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ if (width > (gl::MAX_TEXTURE_SIZE >> level) || height > (gl::MAX_TEXTURE_SIZE >> level))
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ if (width != height)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (width > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level) || height > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level))
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ switch (internalformat)
+ {
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGB:
+ case GL_RGBA:
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // Compressed textures are not supported here, but if they are unsupported altogether,
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: // a different error is generated than otherwise. That is handled below.
+ break;
+ default:
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (border != 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (internalformat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
+ internalformat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
+ {
+ if (context->supportsCompressedTextures())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ 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::Colorbuffer *source = framebuffer->getColorbuffer();
+ if (target == GL_TEXTURE_2D)
+ {
+ gl::Texture2D *texture = context->getTexture2D();
+
+ if (!texture)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ texture->copyImage(level, internalformat, x, y, width, height, source);
+ }
+ else if (gl::IsCubemapTextureTarget(target))
+ {
+ gl::TextureCubeMap *texture = context->getTextureCubeMap();
+
+ if (!texture)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ texture->copyImage(target, level, internalformat, x, y, width, height, source);
+ }
+ 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)
+{
+ TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+ "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
+ target, level, xoffset, yoffset, x, y, width, height);
+
+ try
+ {
+ if (!gl::IsTextureTarget(target))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (level < 0 || level > gl::MAX_TEXTURE_LEVELS || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ 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::Colorbuffer *source = framebuffer->getColorbuffer();
+ if (target == GL_TEXTURE_2D)
+ {
+ gl::Texture2D *texture = context->getTexture2D();
+
+ if (!texture)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ texture->copySubImage(level, xoffset, yoffset, x, y, width, height, source);
+ }
+ else if (gl::IsCubemapTextureTarget(target))
+ {
+ gl::TextureCubeMap *texture = context->getTextureCubeMap();
+
+ if (!texture)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, source);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+ }
+
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+GLuint __stdcall glCreateProgram(void)
+{
+ TRACE("()");
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ return context->createProgram();
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY, 0);
+ }
+
+ return 0;
+}
+
+GLuint __stdcall glCreateShader(GLenum type)
+{
+ TRACE("(GLenum type = 0x%X)", type);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ switch (type)
+ {
+ case GL_FRAGMENT_SHADER:
+ case GL_VERTEX_SHADER:
+ return context->createShader(type);
+ default:
+ return error(GL_INVALID_ENUM, 0);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY, 0);
+ }
+
+ return 0;
+}
+
+void __stdcall glCullFace(GLenum mode)
+{
+ TRACE("(GLenum mode = 0x%X)", mode);
+
+ try
+ {
+ switch (mode)
+ {
+ case GL_FRONT:
+ case GL_BACK:
+ case GL_FRONT_AND_BACK:
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->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)
+{
+ TRACE("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers);
+
+ try
+ {
+ if (n < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ for (int i = 0; i < n; i++)
+ {
+ context->deleteBuffer(buffers[i]);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
+{
+ TRACE("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
+
+ try
+ {
+ if (n < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ for (int i = 0; i < n; i++)
+ {
+ if (framebuffers[i] != 0)
+ {
+ context->deleteFramebuffer(framebuffers[i]);
+ }
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glDeleteProgram(GLuint program)
+{
+ TRACE("(GLuint program = %d)", program);
+
+ try
+ {
+ if (program == 0)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (!context->getProgram(program))
+ {
+ if(context->getShader(program))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ }
+
+ context->deleteProgram(program);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
+{
+ TRACE("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
+
+ try
+ {
+ if (n < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ for (int i = 0; i < n; i++)
+ {
+ context->deleteRenderbuffer(renderbuffers[i]);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glDeleteShader(GLuint shader)
+{
+ TRACE("(GLuint shader = %d)", shader);
+
+ try
+ {
+ if (shader == 0)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (!context->getShader(shader))
+ {
+ if(context->getProgram(shader))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ }
+
+ context->deleteShader(shader);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures)
+{
+ TRACE("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures);
+
+ try
+ {
+ if (n < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ for (int i = 0; i < n; i++)
+ {
+ if (textures[i] != 0)
+ {
+ context->deleteTexture(textures[i]);
+ }
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glDepthFunc(GLenum func)
+{
+ TRACE("(GLenum func = 0x%X)", func);
+
+ try
+ {
+ switch (func)
+ {
+ case GL_NEVER:
+ case GL_ALWAYS:
+ case GL_LESS:
+ case GL_LEQUAL:
+ case GL_EQUAL:
+ case GL_GREATER:
+ case GL_GEQUAL:
+ case GL_NOTEQUAL:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->setDepthFunc(func);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glDepthMask(GLboolean flag)
+{
+ TRACE("(GLboolean flag = %d)", flag);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->setDepthMask(flag != GL_FALSE);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar)
+{
+ TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->setDepthRange(zNear, zFar);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glDetachShader(GLuint program, GLuint shader)
+{
+ TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+
+ gl::Program *programObject = context->getProgram(program);
+ gl::Shader *shaderObject = context->getShader(shader);
+
+ if (!programObject)
+ {
+ 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)
+{
+ TRACE("(GLenum cap = 0x%X)", cap);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ switch (cap)
+ {
+ case GL_CULL_FACE: context->setCullFace(false); break;
+ case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFill(false); break;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(false); break;
+ case GL_SAMPLE_COVERAGE: context->setSampleCoverage(false); break;
+ case GL_SCISSOR_TEST: context->setScissorTest(false); break;
+ case GL_STENCIL_TEST: context->setStencilTest(false); break;
+ case GL_DEPTH_TEST: context->setDepthTest(false); break;
+ case GL_BLEND: context->setBlend(false); break;
+ case GL_DITHER: context->setDither(false); break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glDisableVertexAttribArray(GLuint index)
+{
+ TRACE("(GLuint index = %d)", index);
+
+ try
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->setVertexAttribEnabled(index, false);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+ TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
+
+ try
+ {
+ if (count < 0 || first < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->drawArrays(mode, first, count);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
+{
+ TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)",
+ mode, count, type, indices);
+
+ try
+ {
+ if (count < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT:
+ case GL_UNSIGNED_INT:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->drawElements(mode, count, type, indices);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glEnable(GLenum cap)
+{
+ TRACE("(GLenum cap = 0x%X)", cap);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ switch (cap)
+ {
+ case GL_CULL_FACE: context->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)
+{
+ TRACE("(GLuint index = %d)", index);
+
+ try
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->setVertexAttribEnabled(index, true);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glFinish(void)
+{
+ TRACE("()");
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->finish();
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glFlush(void)
+{
+ TRACE("()");
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->flush();
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+{
+ TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
+ "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
+
+ try
+ {
+ if ((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
+ || renderbuffertarget != GL_RENDERBUFFER)
+ {
+ return error(GL_INVALID_ENUM);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Framebuffer *framebuffer = NULL;
+ GLuint framebufferHandle = 0;
+ if (target == GL_READ_FRAMEBUFFER_ANGLE)
+ {
+ framebuffer = context->getReadFramebuffer();
+ framebufferHandle = context->getReadFramebufferHandle();
+ }
+ else
+ {
+ framebuffer = context->getDrawFramebuffer();
+ framebufferHandle = context->getDrawFramebufferHandle();
+ }
+
+ if (framebufferHandle == 0 || !framebuffer)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ switch (attachment)
+ {
+ case GL_COLOR_ATTACHMENT0:
+ framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer);
+ break;
+ case GL_DEPTH_ATTACHMENT:
+ framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
+ break;
+ case GL_STENCIL_ATTACHMENT:
+ framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+ TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
+ "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
+
+ try
+ {
+ if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
+ {
+ return error(GL_INVALID_ENUM);
+ }
+
+ switch (attachment)
+ {
+ case GL_COLOR_ATTACHMENT0:
+ case GL_DEPTH_ATTACHMENT:
+ case GL_STENCIL_ATTACHMENT:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (texture == 0)
+ {
+ textarget = GL_NONE;
+ }
+ else
+ {
+ gl::Texture *tex = context->getTexture(texture);
+
+ if (tex == NULL)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (tex->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ switch (textarget)
+ {
+ case GL_TEXTURE_2D:
+ if (tex->getTarget() != GL_TEXTURE_2D)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ break;
+
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ break;
+
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (level != 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ }
+
+ gl::Framebuffer *framebuffer = NULL;
+ GLuint framebufferHandle = 0;
+ if (target == GL_READ_FRAMEBUFFER_ANGLE)
+ {
+ framebuffer = context->getReadFramebuffer();
+ framebufferHandle = context->getReadFramebufferHandle();
+ }
+ else
+ {
+ framebuffer = context->getDrawFramebuffer();
+ framebufferHandle = context->getDrawFramebufferHandle();
+ }
+
+ if (framebufferHandle == 0 || !framebuffer)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ switch (attachment)
+ {
+ case GL_COLOR_ATTACHMENT0: framebuffer->setColorbuffer(textarget, texture); break;
+ case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
+ case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glFrontFace(GLenum mode)
+{
+ TRACE("(GLenum mode = 0x%X)", mode);
+
+ try
+ {
+ switch (mode)
+ {
+ case GL_CW:
+ case GL_CCW:
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->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)
+{
+ TRACE("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers);
+
+ try
+ {
+ if (n < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ for (int i = 0; i < n; i++)
+ {
+ buffers[i] = context->createBuffer();
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGenerateMipmap(GLenum target)
+{
+ TRACE("(GLenum target = 0x%X)", target);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Texture *texture;
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ texture = context->getTexture2D();
+ break;
+
+ case GL_TEXTURE_CUBE_MAP:
+ texture = context->getTextureCubeMap();
+ break;
+
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ texture->generateMipmaps();
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers)
+{
+ TRACE("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
+
+ try
+ {
+ if (n < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ for (int i = 0; i < n; i++)
+ {
+ framebuffers[i] = context->createFramebuffer();
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
+{
+ TRACE("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
+
+ try
+ {
+ if (n < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ for (int i = 0; i < n; i++)
+ {
+ renderbuffers[i] = context->createRenderbuffer();
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGenTextures(GLsizei n, GLuint* textures)
+{
+ TRACE("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures);
+
+ try
+ {
+ if (n < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ for (int i = 0; i < n; i++)
+ {
+ textures[i] = context->createTexture();
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+{
+ TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, "
+ "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)",
+ program, index, bufsize, length, size, type, name);
+
+ try
+ {
+ if (bufsize < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ }
+
+ if (index >= (GLuint)programObject->getActiveAttributeCount())
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ programObject->getActiveAttribute(index, bufsize, length, size, type, name);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+{
+ TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
+ "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
+ program, index, bufsize, length, size, type, name);
+
+ try
+ {
+ if (bufsize < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ }
+
+ if (index >= (GLuint)programObject->getActiveUniformCount())
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ programObject->getActiveUniform(index, bufsize, length, size, type, name);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+{
+ TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)",
+ program, maxcount, count, shaders);
+
+ try
+ {
+ if (maxcount < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ }
+
+ return programObject->getAttachedShaders(maxcount, count, shaders);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+int __stdcall glGetAttribLocation(GLuint program, const GLchar* name)
+{
+ TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ return error(GL_INVALID_OPERATION, -1);
+ }
+ else
+ {
+ return error(GL_INVALID_VALUE, -1);
+ }
+ }
+
+ if (!programObject->isLinked())
+ {
+ return error(GL_INVALID_OPERATION, -1);
+ }
+
+ return programObject->getAttributeLocation(name);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY, -1);
+ }
+
+ return -1;
+}
+
+void __stdcall glGetBooleanv(GLenum pname, GLboolean* params)
+{
+ TRACE("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (!(context->getBooleanv(pname, params)))
+ {
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ if (!context->getQueryParameterInfo(pname, &nativeType, &numParams))
+ return error(GL_INVALID_ENUM);
+
+ if (numParams == 0)
+ return; // it is known that the pname is valid, but there are no parameters to return
+
+ if (nativeType == GL_FLOAT)
+ {
+ GLfloat *floatParams = NULL;
+ floatParams = new GLfloat[numParams];
+
+ context->getFloatv(pname, floatParams);
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ if (floatParams[i] == 0.0f)
+ params[i] = GL_FALSE;
+ else
+ params[i] = GL_TRUE;
+ }
+
+ delete [] floatParams;
+ }
+ else if (nativeType == GL_INT)
+ {
+ GLint *intParams = NULL;
+ intParams = new GLint[numParams];
+
+ context->getIntegerv(pname, intParams);
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ if (intParams[i] == 0)
+ params[i] = GL_FALSE;
+ else
+ params[i] = GL_TRUE;
+ }
+
+ delete [] intParams;
+ }
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+ TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Buffer *buffer;
+
+ switch (target)
+ {
+ case GL_ARRAY_BUFFER:
+ buffer = context->getArrayBuffer();
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER:
+ buffer = context->getElementArrayBuffer();
+ break;
+ default: return error(GL_INVALID_ENUM);
+ }
+
+ if (!buffer)
+ {
+ // A null buffer means that "0" is bound to the requested buffer target
+ return error(GL_INVALID_OPERATION);
+ }
+
+ switch (pname)
+ {
+ case GL_BUFFER_USAGE:
+ *params = buffer->usage();
+ break;
+ case GL_BUFFER_SIZE:
+ *params = buffer->size();
+ break;
+ default: return error(GL_INVALID_ENUM);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+GLenum __stdcall glGetError(void)
+{
+ TRACE("()");
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ return context->getError();
+ }
+
+ return GL_NO_ERROR;
+}
+
+void __stdcall glGetFloatv(GLenum pname, GLfloat* params)
+{
+ TRACE("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (!(context->getFloatv(pname, params)))
+ {
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ if (!context->getQueryParameterInfo(pname, &nativeType, &numParams))
+ return error(GL_INVALID_ENUM);
+
+ if (numParams == 0)
+ return; // it is known that the pname is valid, but that there are no parameters to return.
+
+ if (nativeType == GL_BOOL)
+ {
+ GLboolean *boolParams = NULL;
+ boolParams = new GLboolean[numParams];
+
+ context->getBooleanv(pname, boolParams);
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ if (boolParams[i] == GL_FALSE)
+ params[i] = 0.0f;
+ else
+ params[i] = 1.0f;
+ }
+
+ delete [] boolParams;
+ }
+ else if (nativeType == GL_INT)
+ {
+ GLint *intParams = NULL;
+ intParams = new GLint[numParams];
+
+ context->getIntegerv(pname, intParams);
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ params[i] = (GLfloat)intParams[i];
+ }
+
+ delete [] intParams;
+ }
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
+{
+ TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
+ target, attachment, pname, params);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
+ {
+ return error(GL_INVALID_ENUM);
+ }
+
+ gl::Framebuffer *framebuffer = NULL;
+ if (target == GL_READ_FRAMEBUFFER_ANGLE)
+ {
+ if(context->getReadFramebufferHandle() == 0)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ framebuffer = context->getReadFramebuffer();
+ }
+ else
+ {
+ if (context->getDrawFramebufferHandle() == 0)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ framebuffer = context->getDrawFramebuffer();
+ }
+
+ GLenum attachmentType;
+ GLuint attachmentHandle;
+ switch (attachment)
+ {
+ case GL_COLOR_ATTACHMENT0:
+ attachmentType = framebuffer->getColorbufferType();
+ attachmentHandle = framebuffer->getColorbufferHandle();
+ break;
+ case GL_DEPTH_ATTACHMENT:
+ attachmentType = framebuffer->getDepthbufferType();
+ attachmentHandle = framebuffer->getDepthbufferHandle();
+ break;
+ case GL_STENCIL_ATTACHMENT:
+ attachmentType = framebuffer->getStencilbufferType();
+ attachmentHandle = framebuffer->getStencilbufferHandle();
+ break;
+ default: return error(GL_INVALID_ENUM);
+ }
+
+ GLenum attachmentObjectType; // Type category
+ if (attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER)
+ {
+ attachmentObjectType = attachmentType;
+ }
+ else if (gl::IsTextureTarget(attachmentType))
+ {
+ attachmentObjectType = GL_TEXTURE;
+ }
+ else UNREACHABLE();
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ *params = attachmentObjectType;
+ break;
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ if (attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
+ {
+ *params = attachmentHandle;
+ }
+ else
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+ if (attachmentObjectType == GL_TEXTURE)
+ {
+ *params = 0; // FramebufferTexture2D will not allow level to be set to anything else in GL ES 2.0
+ }
+ else
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+ if (attachmentObjectType == GL_TEXTURE)
+ {
+ if (gl::IsCubemapTextureTarget(attachmentType))
+ {
+ *params = attachmentType;
+ }
+ else
+ {
+ *params = 0;
+ }
+ }
+ else
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGetIntegerv(GLenum pname, GLint* params)
+{
+ TRACE("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ 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)
+{
+ TRACE("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ switch (pname)
+ {
+ case GL_DELETE_STATUS:
+ *params = programObject->isFlaggedForDeletion();
+ return;
+ case GL_LINK_STATUS:
+ *params = programObject->isLinked();
+ return;
+ case GL_VALIDATE_STATUS:
+ *params = programObject->isValidated();
+ return;
+ case GL_INFO_LOG_LENGTH:
+ *params = programObject->getInfoLogLength();
+ return;
+ case GL_ATTACHED_SHADERS:
+ *params = programObject->getAttachedShadersCount();
+ return;
+ case GL_ACTIVE_ATTRIBUTES:
+ *params = programObject->getActiveAttributeCount();
+ return;
+ case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+ *params = programObject->getActiveAttributeMaxLength();
+ return;
+ case GL_ACTIVE_UNIFORMS:
+ *params = programObject->getActiveUniformCount();
+ return;
+ case GL_ACTIVE_UNIFORM_MAX_LENGTH:
+ *params = programObject->getActiveUniformMaxLength();
+ return;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+{
+ TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
+ program, bufsize, length, infolog);
+
+ try
+ {
+ if (bufsize < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ programObject->getInfoLog(bufsize, length, infolog);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+ TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (target != GL_RENDERBUFFER)
+ {
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (context->getRenderbufferHandle() == 0)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferHandle());
+
+ switch (pname)
+ {
+ case GL_RENDERBUFFER_WIDTH:
+ *params = renderbuffer->getWidth();
+ break;
+ case GL_RENDERBUFFER_HEIGHT:
+ *params = renderbuffer->getHeight();
+ break;
+ case GL_RENDERBUFFER_INTERNAL_FORMAT:
+ *params = renderbuffer->getFormat();
+ break;
+ case GL_RENDERBUFFER_RED_SIZE:
+ if (renderbuffer->isColorbuffer())
+ {
+ *params = static_cast<gl::Colorbuffer*>(renderbuffer->getStorage())->getRedSize();
+ }
+ else
+ {
+ *params = 0;
+ }
+ break;
+ case GL_RENDERBUFFER_GREEN_SIZE:
+ if (renderbuffer->isColorbuffer())
+ {
+ *params = static_cast<gl::Colorbuffer*>(renderbuffer->getStorage())->getGreenSize();
+ }
+ else
+ {
+ *params = 0;
+ }
+ break;
+ case GL_RENDERBUFFER_BLUE_SIZE:
+ if (renderbuffer->isColorbuffer())
+ {
+ *params = static_cast<gl::Colorbuffer*>(renderbuffer->getStorage())->getBlueSize();
+ }
+ else
+ {
+ *params = 0;
+ }
+ break;
+ case GL_RENDERBUFFER_ALPHA_SIZE:
+ if (renderbuffer->isColorbuffer())
+ {
+ *params = static_cast<gl::Colorbuffer*>(renderbuffer->getStorage())->getAlphaSize();
+ }
+ else
+ {
+ *params = 0;
+ }
+ break;
+ case GL_RENDERBUFFER_DEPTH_SIZE:
+ if (renderbuffer->isDepthbuffer())
+ {
+ *params = static_cast<gl::Depthbuffer*>(renderbuffer->getStorage())->getDepthSize();
+ }
+ else
+ {
+ *params = 0;
+ }
+ break;
+ case GL_RENDERBUFFER_STENCIL_SIZE:
+ if (renderbuffer->isStencilbuffer())
+ {
+ *params = static_cast<gl::Stencilbuffer*>(renderbuffer->getStorage())->getStencilSize();
+ }
+ else
+ {
+ *params = 0;
+ }
+ break;
+ case GL_RENDERBUFFER_SAMPLES_ANGLE:
+ {
+ if (context->getMaxSupportedSamples() != 0)
+ {
+ *params = renderbuffer->getStorage()->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)
+{
+ TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Shader *shaderObject = context->getShader(shader);
+
+ if (!shaderObject)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ switch (pname)
+ {
+ case GL_SHADER_TYPE:
+ *params = shaderObject->getType();
+ return;
+ case GL_DELETE_STATUS:
+ *params = shaderObject->isFlaggedForDeletion();
+ return;
+ case GL_COMPILE_STATUS:
+ *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
+ return;
+ case GL_INFO_LOG_LENGTH:
+ *params = shaderObject->getInfoLogLength();
+ return;
+ case GL_SHADER_SOURCE_LENGTH:
+ *params = shaderObject->getSourceLength();
+ return;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+{
+ TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
+ shader, bufsize, length, infolog);
+
+ try
+ {
+ if (bufsize < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Shader *shaderObject = context->getShader(shader);
+
+ if (!shaderObject)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ shaderObject->getInfoLog(bufsize, length, infolog);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+{
+ TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)",
+ shadertype, precisiontype, range, precision);
+
+ try
+ {
+ 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)
+{
+ TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
+ shader, bufsize, length, source);
+
+ try
+ {
+ if (bufsize < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Shader *shaderObject = context->getShader(shader);
+
+ if (!shaderObject)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ shaderObject->getSource(bufsize, length, source);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+const GLubyte* __stdcall glGetString(GLenum name)
+{
+ TRACE("(GLenum name = 0x%X)", name);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ switch (name)
+ {
+ case GL_VENDOR:
+ return (GLubyte*)"TransGaming Inc.";
+ case GL_RENDERER:
+ return (GLubyte*)"ANGLE";
+ case GL_VERSION:
+ return (GLubyte*)"OpenGL ES 2.0 (git-devel "__DATE__ " " __TIME__")";
+ case GL_SHADING_LANGUAGE_VERSION:
+ return (GLubyte*)"OpenGL ES GLSL ES 1.00 (git-devel "__DATE__ " " __TIME__")";
+ case GL_EXTENSIONS:
+ return (GLubyte*)((context != NULL) ? context->getExtensionString() : "");
+ default:
+ return error(GL_INVALID_ENUM, (GLubyte*)NULL);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY, (GLubyte*)NULL);
+ }
+
+ return NULL;
+}
+
+void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
+{
+ TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Texture *texture;
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ texture = context->getTexture2D();
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ texture = context->getTextureCubeMap();
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_MAG_FILTER:
+ *params = (GLfloat)texture->getMagFilter();
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = (GLfloat)texture->getMinFilter();
+ break;
+ case GL_TEXTURE_WRAP_S:
+ *params = (GLfloat)texture->getWrapS();
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = (GLfloat)texture->getWrapT();
+ break;
+ 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)
+{
+ TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Texture *texture;
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ texture = context->getTexture2D();
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ texture = context->getTextureCubeMap();
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_MAG_FILTER:
+ *params = texture->getMagFilter();
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = texture->getMinFilter();
+ break;
+ case GL_TEXTURE_WRAP_S:
+ *params = texture->getWrapS();
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = texture->getWrapT();
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params)
+{
+ TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (program == 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject || !programObject->isLinked())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!programObject->getUniformfv(location, 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)
+{
+ TRACE("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (program == 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject || !programObject->isLinked())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!programObject)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!programObject->getUniformiv(location, params))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+int __stdcall glGetUniformLocation(GLuint program, const GLchar* name)
+{
+ TRACE("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (strstr(name, "gl_") == name)
+ {
+ return -1;
+ }
+
+ if (context)
+ {
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ return error(GL_INVALID_OPERATION, -1);
+ }
+ else
+ {
+ return error(GL_INVALID_VALUE, -1);
+ }
+ }
+
+ if (!programObject->isLinked())
+ {
+ return error(GL_INVALID_OPERATION, -1);
+ }
+
+ return programObject->getUniformLocation(name, false);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY, -1);
+ }
+
+ return -1;
+}
+
+void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
+{
+ TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ const gl::AttributeState &attribState = context->getVertexAttribState(index);
+
+ switch (pname)
+ {
+ case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
+ *params = (GLfloat)(attribState.mEnabled ? GL_TRUE : GL_FALSE);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_SIZE:
+ *params = (GLfloat)attribState.mSize;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
+ *params = (GLfloat)attribState.mStride;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_TYPE:
+ *params = (GLfloat)attribState.mType;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
+ *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
+ *params = (GLfloat)attribState.mBoundBuffer.id();
+ break;
+ case GL_CURRENT_VERTEX_ATTRIB:
+ for (int i = 0; i < 4; ++i)
+ {
+ params[i] = attribState.mCurrentValue[i];
+ }
+ break;
+ default: return error(GL_INVALID_ENUM);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
+{
+ TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ const gl::AttributeState &attribState = context->getVertexAttribState(index);
+
+ switch (pname)
+ {
+ case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
+ *params = (attribState.mEnabled ? GL_TRUE : GL_FALSE);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_SIZE:
+ *params = attribState.mSize;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
+ *params = attribState.mStride;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_TYPE:
+ *params = attribState.mType;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
+ *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
+ *params = attribState.mBoundBuffer.id();
+ break;
+ case GL_CURRENT_VERTEX_ATTRIB:
+ for (int i = 0; i < 4; ++i)
+ {
+ float currentValue = attribState.mCurrentValue[i];
+ params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
+ }
+ break;
+ default: return error(GL_INVALID_ENUM);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
+{
+ TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
+ {
+ return error(GL_INVALID_ENUM);
+ }
+
+ *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glHint(GLenum target, GLenum mode)
+{
+ TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
+
+ try
+ {
+ switch (target)
+ {
+ case GL_GENERATE_MIPMAP_HINT:
+ switch (mode)
+ {
+ case GL_FASTEST:
+ case GL_NICEST:
+ case GL_DONT_CARE:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ gl::Context *context = gl::getContext();
+ if (context)
+ {
+ if (target == GL_GENERATE_MIPMAP_HINT)
+ context->setGenerateMipmapHint(mode);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+GLboolean __stdcall glIsBuffer(GLuint buffer)
+{
+ TRACE("(GLuint buffer = %d)", buffer);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context && buffer)
+ {
+ gl::Buffer *bufferObject = context->getBuffer(buffer);
+
+ if (bufferObject)
+ {
+ return GL_TRUE;
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY, GL_FALSE);
+ }
+
+ return GL_FALSE;
+}
+
+GLboolean __stdcall glIsEnabled(GLenum cap)
+{
+ TRACE("(GLenum cap = 0x%X)", cap);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ switch (cap)
+ {
+ case GL_CULL_FACE: return context->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 glIsFramebuffer(GLuint framebuffer)
+{
+ TRACE("(GLuint framebuffer = %d)", framebuffer);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context && framebuffer)
+ {
+ gl::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
+
+ if (framebufferObject)
+ {
+ return GL_TRUE;
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY, GL_FALSE);
+ }
+
+ return GL_FALSE;
+}
+
+GLboolean __stdcall glIsProgram(GLuint program)
+{
+ TRACE("(GLuint program = %d)", program);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context && program)
+ {
+ gl::Program *programObject = context->getProgram(program);
+
+ if (programObject)
+ {
+ return GL_TRUE;
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY, GL_FALSE);
+ }
+
+ return GL_FALSE;
+}
+
+GLboolean __stdcall glIsRenderbuffer(GLuint renderbuffer)
+{
+ TRACE("(GLuint renderbuffer = %d)", renderbuffer);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context && renderbuffer)
+ {
+ gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
+
+ if (renderbufferObject)
+ {
+ return GL_TRUE;
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY, GL_FALSE);
+ }
+
+ return GL_FALSE;
+}
+
+GLboolean __stdcall glIsShader(GLuint shader)
+{
+ TRACE("(GLuint shader = %d)", shader);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context && shader)
+ {
+ gl::Shader *shaderObject = context->getShader(shader);
+
+ if (shaderObject)
+ {
+ return GL_TRUE;
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY, GL_FALSE);
+ }
+
+ return GL_FALSE;
+}
+
+GLboolean __stdcall glIsTexture(GLuint texture)
+{
+ TRACE("(GLuint texture = %d)", texture);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context && texture)
+ {
+ gl::Texture *textureObject = context->getTexture(texture);
+
+ if (textureObject)
+ {
+ return GL_TRUE;
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY, GL_FALSE);
+ }
+
+ return GL_FALSE;
+}
+
+void __stdcall glLineWidth(GLfloat width)
+{
+ TRACE("(GLfloat width = %f)", width);
+
+ try
+ {
+ if (width <= 0.0f)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->setLineWidth(width);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glLinkProgram(GLuint program)
+{
+ TRACE("(GLuint program = %d)", program);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ }
+
+ programObject->link();
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glPixelStorei(GLenum pname, GLint param)
+{
+ TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ switch (pname)
+ {
+ case GL_UNPACK_ALIGNMENT:
+ if (param != 1 && param != 2 && param != 4 && param != 8)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ context->setUnpackAlignment(param);
+ break;
+
+ case GL_PACK_ALIGNMENT:
+ if (param != 1 && param != 2 && param != 4 && param != 8)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ context->setPackAlignment(param);
+ break;
+
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glPolygonOffset(GLfloat factor, GLfloat units)
+{
+ TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->setPolygonOffsetParams(factor, units);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
+{
+ TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
+ "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)",
+ x, y, width, height, format, type, pixels);
+
+ try
+ {
+ if (width < 0 || height < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ switch (format)
+ {
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ default:
+ return error(GL_INVALID_OPERATION);
+ }
+ 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 error(GL_INVALID_OPERATION);
+ }
+ break;
+ case gl::IMPLEMENTATION_COLOR_READ_FORMAT:
+ switch (type)
+ {
+ case gl::IMPLEMENTATION_COLOR_READ_TYPE:
+ break;
+ default:
+ return error(GL_INVALID_OPERATION);
+ }
+ break;
+ default:
+ return error(GL_INVALID_OPERATION);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->readPixels(x, y, width, height, format, type, pixels);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glReleaseShaderCompiler(void)
+{
+ TRACE("()");
+
+ try
+ {
+ gl::Shader::releaseCompiler();
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
+ target, samples, internalformat, width, height);
+
+ try
+ {
+ switch (target)
+ {
+ case GL_RENDERBUFFER:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ switch (internalformat)
+ {
+ case GL_DEPTH_COMPONENT16:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGB565:
+ case GL_STENCIL_INDEX8:
+ case GL_DEPTH24_STENCIL8_OES:
+ case GL_RGB8_OES:
+ case GL_RGBA8_OES:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (width < 0 || height < 0 || width > gl::MAX_RENDERBUFFER_SIZE || height > gl::MAX_RENDERBUFFER_SIZE || samples < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (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)
+{
+ TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
+
+ try
+ {
+ gl::Context* context = gl::getContext();
+
+ if (context)
+ {
+ context->setSampleCoverageParams(gl::clamp01(value), invert == GL_TRUE);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
+
+ try
+ {
+ if (width < 0 || height < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context* context = gl::getContext();
+
+ if (context)
+ {
+ context->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)
+{
+ TRACE("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, "
+ "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
+ n, shaders, binaryformat, binary, length);
+
+ try
+ {
+ // No binary shader formats are supported.
+ return error(GL_INVALID_ENUM);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar** string, const GLint* length)
+{
+ TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)",
+ shader, count, string, length);
+
+ try
+ {
+ if (count < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Shader *shaderObject = context->getShader(shader);
+
+ if (!shaderObject)
+ {
+ if (context->getProgram(shader))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ }
+
+ shaderObject->setSource(count, string, length);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glStencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+ glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
+}
+
+void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+ TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
+
+ try
+ {
+ switch (face)
+ {
+ case GL_FRONT:
+ case GL_BACK:
+ case GL_FRONT_AND_BACK:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ switch (func)
+ {
+ case GL_NEVER:
+ case GL_ALWAYS:
+ case GL_LESS:
+ case GL_LEQUAL:
+ case GL_EQUAL:
+ case GL_GEQUAL:
+ case GL_GREATER:
+ case GL_NOTEQUAL:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+ {
+ context->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)
+{
+ TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
+
+ try
+ {
+ switch (face)
+ {
+ case GL_FRONT:
+ case GL_BACK:
+ case GL_FRONT_AND_BACK:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+ {
+ context->setStencilWritemask(mask);
+ }
+
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+ {
+ context->setStencilBackWritemask(mask);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+{
+ glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
+}
+
+void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+{
+ TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
+ face, fail, zfail, zpass);
+
+ try
+ {
+ switch (face)
+ {
+ case GL_FRONT:
+ case GL_BACK:
+ case GL_FRONT_AND_BACK:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ switch (fail)
+ {
+ case GL_ZERO:
+ case GL_KEEP:
+ case GL_REPLACE:
+ case GL_INCR:
+ case GL_DECR:
+ case GL_INVERT:
+ case GL_INCR_WRAP:
+ case GL_DECR_WRAP:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ switch (zfail)
+ {
+ case GL_ZERO:
+ case GL_KEEP:
+ case GL_REPLACE:
+ case GL_INCR:
+ case GL_DECR:
+ case GL_INVERT:
+ case GL_INCR_WRAP:
+ case GL_DECR_WRAP:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ switch (zpass)
+ {
+ case GL_ZERO:
+ case GL_KEEP:
+ case GL_REPLACE:
+ case GL_INCR:
+ case GL_DECR:
+ case GL_INVERT:
+ case GL_INCR_WRAP:
+ case GL_DECR_WRAP:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+ {
+ context->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);
+ }
+}
+
+void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
+ GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+{
+ TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
+ "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
+ target, level, internalformat, width, height, border, format, type, pixels);
+
+ try
+ {
+ if (level < 0 || width < 0 || height < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (level > 0 && (!gl::isPow2(width) || !gl::isPow2(height)))
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ if (width > (gl::MAX_TEXTURE_SIZE >> level) || height > (gl::MAX_TEXTURE_SIZE >> level))
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ if (width != height)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (width > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level) || height > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level))
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (internalformat != format)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ switch (internalformat)
+ {
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_RGB:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT_5_6_5:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_BGRA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ break;
+ default:
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (border != 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (internalformat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
+ internalformat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
+ {
+ if (context->supportsCompressedTextures())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ }
+
+ if (target == GL_TEXTURE_2D)
+ {
+ gl::Texture2D *texture = context->getTexture2D();
+
+ if (!texture)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ texture->setImage(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
+ }
+ else
+ {
+ gl::TextureCubeMap *texture = context->getTextureCubeMap();
+
+ if (!texture)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ switch (target)
+ {
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ texture->setImagePosX(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ texture->setImageNegX(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ texture->setImagePosY(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ texture->setImageNegY(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ texture->setImagePosZ(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ texture->setImageNegZ(level, internalformat, 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)
+{
+ glTexParameteri(target, pname, (GLint)param);
+}
+
+void __stdcall glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
+{
+ glTexParameteri(target, pname, (GLint)*params);
+}
+
+void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param)
+{
+ TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Texture *texture;
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ texture = context->getTexture2D();
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ texture = context->getTextureCubeMap();
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ if (!texture->setWrapS((GLenum)param))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_WRAP_T:
+ if (!texture->setWrapT((GLenum)param))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ if (!texture->setMinFilter((GLenum)param))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ if (!texture->setMagFilter((GLenum)param))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
+{
+ glTexParameteri(target, pname, *params);
+}
+
+void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const GLvoid* pixels)
+{
+ TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+ "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
+ "const GLvoid* pixels = 0x%0.8p)",
+ target, level, xoffset, yoffset, width, height, format, type, pixels);
+
+ try
+ {
+ if (!gl::IsTextureTarget(target))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (level < 0 || level > gl::MAX_TEXTURE_LEVELS || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (!gl::CheckTextureFormatType(format, type))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (width == 0 || height == 0 || pixels == NULL)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (target == GL_TEXTURE_2D)
+ {
+ gl::Texture2D *texture = context->getTexture2D();
+
+ if (!texture)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
+ }
+ else if (gl::IsCubemapTextureTarget(target))
+ {
+ gl::TextureCubeMap *texture = context->getTextureCubeMap();
+
+ if (!texture)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (texture->isCompressed())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ 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)
+{
+ TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+
+ try
+ {
+ if (count < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (location == -1)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *program = context->getCurrentProgram();
+
+ if (!program)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!program->setUniform1fv(location, count, v))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glUniform1i(GLint location, GLint x)
+{
+ glUniform1iv(location, 1, &x);
+}
+
+void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v)
+{
+ TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+
+ try
+ {
+ if (count < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (location == -1)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *program = context->getCurrentProgram();
+
+ if (!program)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!program->setUniform1iv(location, count, v))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glUniform2f(GLint location, GLfloat x, GLfloat y)
+{
+ GLfloat xy[2] = {x, y};
+
+ glUniform2fv(location, 1, (GLfloat*)&xy);
+}
+
+void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
+{
+ TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+
+ try
+ {
+ if (count < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (location == -1)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *program = context->getCurrentProgram();
+
+ if (!program)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!program->setUniform2fv(location, count, v))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glUniform2i(GLint location, GLint x, GLint y)
+{
+ GLint xy[4] = {x, y};
+
+ glUniform2iv(location, 1, (GLint*)&xy);
+}
+
+void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v)
+{
+ TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+
+ try
+ {
+ if (count < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (location == -1)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *program = context->getCurrentProgram();
+
+ if (!program)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!program->setUniform2iv(location, count, v))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+ GLfloat xyz[3] = {x, y, z};
+
+ glUniform3fv(location, 1, (GLfloat*)&xyz);
+}
+
+void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
+{
+ TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+
+ try
+ {
+ if (count < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (location == -1)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *program = context->getCurrentProgram();
+
+ if (!program)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!program->setUniform3fv(location, count, v))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glUniform3i(GLint location, GLint x, GLint y, GLint z)
+{
+ GLint xyz[3] = {x, y, z};
+
+ glUniform3iv(location, 1, (GLint*)&xyz);
+}
+
+void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v)
+{
+ TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+
+ try
+ {
+ if (count < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (location == -1)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *program = context->getCurrentProgram();
+
+ if (!program)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!program->setUniform3iv(location, count, v))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GLfloat xyzw[4] = {x, y, z, w};
+
+ glUniform4fv(location, 1, (GLfloat*)&xyzw);
+}
+
+void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
+{
+ TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+
+ try
+ {
+ if (count < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (location == -1)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *program = context->getCurrentProgram();
+
+ if (!program)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!program->setUniform4fv(location, count, v))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
+{
+ GLint xyzw[4] = {x, y, z, w};
+
+ glUniform4iv(location, 1, (GLint*)&xyzw);
+}
+
+void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v)
+{
+ TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+
+ try
+ {
+ if (count < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (location == -1)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *program = context->getCurrentProgram();
+
+ if (!program)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!program->setUniform4iv(location, count, v))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ try
+ {
+ if (count < 0 || transpose != GL_FALSE)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (location == -1)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *program = context->getCurrentProgram();
+
+ if (!program)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!program->setUniformMatrix2fv(location, count, value))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ try
+ {
+ if (count < 0 || transpose != GL_FALSE)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (location == -1)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *program = context->getCurrentProgram();
+
+ if (!program)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!program->setUniformMatrix3fv(location, count, value))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ try
+ {
+ if (count < 0 || transpose != GL_FALSE)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (location == -1)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *program = context->getCurrentProgram();
+
+ if (!program)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!program->setUniformMatrix4fv(location, count, value))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glUseProgram(GLuint program)
+{
+ TRACE("(GLuint program = %d)", program);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject && 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)
+{
+ TRACE("(GLuint program = %d)", program);
+
+ try
+ {
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ }
+
+ programObject->validate();
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glVertexAttrib1f(GLuint index, GLfloat x)
+{
+ TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
+
+ try
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ GLfloat vals[4] = { x, 0, 0, 1 };
+ context->setVertexAttrib(index, vals);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values)
+{
+ TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+
+ try
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ GLfloat vals[4] = { values[0], 0, 0, 1 };
+ context->setVertexAttrib(index, vals);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
+{
+ TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
+
+ try
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ GLfloat vals[4] = { x, y, 0, 1 };
+ context->setVertexAttrib(index, vals);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values)
+{
+ TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+
+ try
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ GLfloat vals[4] = { values[0], values[1], 0, 1 };
+ context->setVertexAttrib(index, vals);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+{
+ TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
+
+ try
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ GLfloat vals[4] = { x, y, z, 1 };
+ context->setVertexAttrib(index, vals);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values)
+{
+ TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+
+ try
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ GLfloat vals[4] = { values[0], values[1], values[2], 1 };
+ context->setVertexAttrib(index, vals);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
+
+ try
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ GLfloat vals[4] = { x, y, z, w };
+ context->setVertexAttrib(index, vals);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values)
+{
+ TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+
+ try
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->setVertexAttrib(index, values);
+ }
+ }
+ 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)
+{
+ TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
+ "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)",
+ index, size, type, normalized, stride, ptr);
+
+ try
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (size < 1 || size > 4)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ switch (type)
+ {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ case GL_FIXED:
+ case GL_FLOAT:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (stride < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), stride, ptr);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
+
+ try
+ {
+ if (width < 0 || height < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ context->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)
+{
+ TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
+ "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
+ "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
+ srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+
+ try
+ {
+ switch (filter)
+ {
+ case GL_NEAREST:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
+ {
+ ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
+ return error(GL_INVALID_OPERATION);
+ }
+
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle())
+ {
+ ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
+ return error(GL_INVALID_OPERATION);
+ }
+
+ context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+{
+ TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
+ "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
+ "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)",
+ target, level, internalformat, width, height, depth, border, format, type, pixels);
+
+ try
+ {
+ UNIMPLEMENTED(); // FIXME
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname)
+{
+ struct Extension
+ {
+ const char *name;
+ __eglMustCastToProperFunctionPointerType address;
+ };
+
+ static const Extension glExtensions[] =
+ {
+ {"glTexImage3DOES", (__eglMustCastToProperFunctionPointerType)glTexImage3DOES},
+ {"glBlitFramebufferANGLE", (__eglMustCastToProperFunctionPointerType)glBlitFramebufferANGLE},
+ };
+
+ for (int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++)
+ {
+ if (strcmp(procname, glExtensions[ext].name) == 0)
+ {
+ return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address;
+ }
+ }
+
+ return NULL;
+}
+
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.def b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.def
new file mode 100644
index 0000000..a043ed8
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.def
@@ -0,0 +1,156 @@
+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
+
+ ; EGL dependencies
+ glCreateContext @144 NONAME
+ glDestroyContext @145 NONAME
+ glMakeCurrent @146 NONAME
+ glGetCurrentContext @147 NONAME
+ glGetProcAddress @148 NONAME \ No newline at end of file
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.vcproj b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.vcproj
new file mode 100644
index 0000000..1f43e7a
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.vcproj
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="libGLESv2"
+ ProjectGUID="{B5871A7A-968C-42E3-A33B-981E6F448E78}"
+ RootNamespace="libGLESv2"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(ProjectDir)/..; $(ProjectDir)/../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="D3dx9.lib"
+ LinkIncremental="2"
+ ModuleDefinitionFile="libGLESv2.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="@echo on&#x0D;&#x0A;mkdir &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;copy &quot;$(OutDir)\libGLESv2.dll&quot; &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;copy &quot;$(OutDir)\libGLESv2.lib&quot; &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;@echo off&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="2"
+ AdditionalIncludeDirectories="$(ProjectDir)/..; $(ProjectDir)/../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="D3dx9.lib"
+ LinkIncremental="1"
+ IgnoreAllDefaultLibraries="false"
+ ModuleDefinitionFile="libGLESv2.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="@echo on&#x0D;&#x0A;mkdir &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;copy &quot;$(OutDir)\libGLESv2.dll&quot; &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;copy &quot;$(OutDir)\libGLESv2.lib&quot; &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;@echo off&#x0D;&#x0A;"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\Blit.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Buffer.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Context.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\common\debug.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Framebuffer.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libGLESv2.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\main.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Program.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\RefCountObject.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Renderbuffer.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ResourceManager.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Shader.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Texture.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\utilities.cpp"
+ >
+ </File>
+ <Filter
+ Name="Geometry"
+ >
+ <File
+ RelativePath=".\geometry\backend.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\geometry\dx9.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\geometry\IndexDataManager.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\geometry\VertexDataManager.cpp"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\Blit.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Buffer.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Context.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Framebuffer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\GLES2\gl2.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\GLES2\gl2ext.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\GLES2\gl2platform.h"
+ >
+ </File>
+ <File
+ RelativePath=".\main.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mathutil.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Program.h"
+ >
+ </File>
+ <File
+ RelativePath=".\RefCountObject.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Renderbuffer.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ResourceManager.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Shader.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Texture.h"
+ >
+ </File>
+ <File
+ RelativePath=".\utilities.h"
+ >
+ </File>
+ <Filter
+ Name="Geometry"
+ >
+ <File
+ RelativePath=".\geometry\backend.h"
+ >
+ </File>
+ <File
+ RelativePath=".\geometry\dx9.h"
+ >
+ </File>
+ <File
+ RelativePath=".\geometry\IndexDataManager.h"
+ >
+ </File>
+ <File
+ RelativePath=".\geometry\vertexconversion.h"
+ >
+ </File>
+ <File
+ RelativePath=".\geometry\VertexDataManager.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <File
+ RelativePath=".\libGLESv2.def"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/main.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/main.cpp
new file mode 100644
index 0000000..a99ec44
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/main.cpp
@@ -0,0 +1,143 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// main.cpp: DLL entry point and management of thread-local data.
+
+#include "libGLESv2/main.h"
+
+#include "common/debug.h"
+#include "libEGL/Surface.h"
+
+#include "libGLESv2/Framebuffer.h"
+
+static DWORD currentTLS = TLS_OUT_OF_INDEXES;
+
+BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
+{
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ currentTLS = TlsAlloc();
+
+ if (currentTLS == TLS_OUT_OF_INDEXES)
+ {
+ return FALSE;
+ }
+ }
+ // Fall throught to initialize index
+ case DLL_THREAD_ATTACH:
+ {
+ gl::Current *current = (gl::Current*)LocalAlloc(LPTR, sizeof(gl::Current));
+
+ if (current)
+ {
+ TlsSetValue(currentTLS, current);
+
+ current->context = NULL;
+ current->display = NULL;
+ }
+ }
+ break;
+ case DLL_THREAD_DETACH:
+ {
+ void *current = TlsGetValue(currentTLS);
+
+ if (current)
+ {
+ LocalFree((HLOCAL)current);
+ }
+ }
+ break;
+ case DLL_PROCESS_DETACH:
+ {
+ void *current = TlsGetValue(currentTLS);
+
+ if (current)
+ {
+ LocalFree((HLOCAL)current);
+ }
+
+ TlsFree(currentTLS);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+namespace gl
+{
+void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)
+{
+ Current *current = (Current*)TlsGetValue(currentTLS);
+
+ current->context = context;
+ current->display = display;
+
+ if (context && display && surface)
+ {
+ context->makeCurrent(display, surface);
+ }
+}
+
+Context *getContext()
+{
+ Current *current = (Current*)TlsGetValue(currentTLS);
+
+ return current->context;
+}
+
+egl::Display *getDisplay()
+{
+ Current *current = (Current*)TlsGetValue(currentTLS);
+
+ return current->display;
+}
+
+IDirect3DDevice9 *getDevice()
+{
+ egl::Display *display = getDisplay();
+
+ return display->getDevice();
+}
+}
+
+// Records an error code
+void error(GLenum errorCode)
+{
+ gl::Context *context = glGetCurrentContext();
+
+ if (context)
+ {
+ switch (errorCode)
+ {
+ case GL_INVALID_ENUM:
+ context->recordInvalidEnum();
+ gl::trace("\t! Error generated: invalid enum\n");
+ break;
+ case GL_INVALID_VALUE:
+ context->recordInvalidValue();
+ gl::trace("\t! Error generated: invalid value\n");
+ break;
+ case GL_INVALID_OPERATION:
+ context->recordInvalidOperation();
+ gl::trace("\t! Error generated: invalid operation\n");
+ break;
+ case GL_OUT_OF_MEMORY:
+ context->recordOutOfMemory();
+ gl::trace("\t! Error generated: out of memory\n");
+ break;
+ case GL_INVALID_FRAMEBUFFER_OPERATION:
+ context->recordInvalidFramebufferOperation();
+ gl::trace("\t! Error generated: invalid framebuffer operation\n");
+ break;
+ default: UNREACHABLE();
+ }
+ }
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/main.h b/Source/ThirdParty/ANGLE/src/libGLESv2/main.h
new file mode 100644
index 0000000..7f9c880
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/main.h
@@ -0,0 +1,47 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// 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();
+egl::Display *getDisplay();
+
+IDirect3DDevice9 *getDevice();
+}
+
+void error(GLenum errorCode);
+
+template<class T>
+const T &error(GLenum errorCode, const T &returnValue)
+{
+ error(errorCode);
+
+ return returnValue;
+}
+
+#endif // LIBGLESV2_MAIN_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/mathutil.h b/Source/ThirdParty/ANGLE/src/libGLESv2/mathutil.h
new file mode 100644
index 0000000..31fa16f
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/mathutil.h
@@ -0,0 +1,66 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// mathutil.h: Math and bit manipulation functions.
+
+#ifndef LIBGLESV2_MATHUTIL_H_
+#define LIBGLESV2_MATHUTIL_H_
+
+#include <math.h>
+
+namespace gl
+{
+inline bool isPow2(int x)
+{
+ return (x & (x - 1)) == 0 && (x != 0);
+}
+
+inline int log2(int x)
+{
+ int r = 0;
+ while ((x >> r) > 1) r++;
+ return r;
+}
+
+inline 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;
+}
+
+inline float clamp01(float x)
+{
+ return x < 0 ? 0 : (x > 1 ? 1 : x);
+}
+
+template<const int n>
+inline unsigned int unorm(float x)
+{
+ const unsigned int max = 0xFFFFFFFF >> (32 - n);
+
+ if (x > 1)
+ {
+ return max;
+ }
+ else if (x < 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return (unsigned int)(max * x + 0.5f);
+ }
+}
+}
+
+#endif // LIBGLESV2_MATHUTIL_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.cpp
new file mode 100644
index 0000000..7fc2bc4
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.cpp
@@ -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.
+//
+
+// utilities.cpp: Conversion functions and other utility routines.
+
+#include "libGLESv2/utilities.h"
+
+#include <limits>
+
+#include "common/debug.h"
+
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/Context.h"
+
+namespace gl
+{
+
+int UniformComponentCount(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BOOL:
+ case GL_FLOAT:
+ case GL_INT:
+ return 1;
+ case GL_BOOL_VEC2:
+ case GL_FLOAT_VEC2:
+ case GL_INT_VEC2:
+ return 2;
+ case GL_INT_VEC3:
+ case GL_FLOAT_VEC3:
+ case GL_BOOL_VEC3:
+ return 3;
+ case GL_BOOL_VEC4:
+ case GL_FLOAT_VEC4:
+ case GL_INT_VEC4:
+ case GL_FLOAT_MAT2:
+ return 4;
+ case GL_FLOAT_MAT3:
+ return 9;
+ case GL_FLOAT_MAT4:
+ return 16;
+ default:
+ UNREACHABLE();
+ }
+
+ return 0;
+}
+
+GLenum UniformComponentType(GLenum type)
+{
+ switch(type)
+ {
+ case GL_BOOL:
+ case GL_BOOL_VEC2:
+ case GL_BOOL_VEC3:
+ case GL_BOOL_VEC4:
+ return GL_BOOL;
+ case GL_FLOAT:
+ case GL_FLOAT_VEC2:
+ case GL_FLOAT_VEC3:
+ case GL_FLOAT_VEC4:
+ case GL_FLOAT_MAT2:
+ case GL_FLOAT_MAT3:
+ case GL_FLOAT_MAT4:
+ return GL_FLOAT;
+ case GL_INT:
+ case GL_INT_VEC2:
+ case GL_INT_VEC3:
+ case GL_INT_VEC4:
+ return GL_INT;
+ default:
+ UNREACHABLE();
+ }
+
+ return GL_NONE;
+}
+
+size_t UniformTypeSize(GLenum type)
+{
+ switch(type)
+ {
+ case GL_BOOL: return sizeof(GLboolean);
+ case GL_FLOAT: return sizeof(GLfloat);
+ case GL_INT: return sizeof(GLint);
+ }
+
+ return UniformTypeSize(UniformComponentType(type)) * UniformComponentCount(type);
+}
+
+int VariableRowCount(GLenum type)
+{
+ switch (type)
+ {
+ case GL_NONE:
+ return 0;
+ case GL_BOOL:
+ case GL_FLOAT:
+ case GL_INT:
+ case GL_BOOL_VEC2:
+ case GL_FLOAT_VEC2:
+ case GL_INT_VEC2:
+ case GL_INT_VEC3:
+ case GL_FLOAT_VEC3:
+ case GL_BOOL_VEC3:
+ case GL_BOOL_VEC4:
+ case GL_FLOAT_VEC4:
+ case GL_INT_VEC4:
+ return 1;
+ case GL_FLOAT_MAT2:
+ return 2;
+ case GL_FLOAT_MAT3:
+ return 3;
+ case GL_FLOAT_MAT4:
+ return 4;
+ default:
+ UNREACHABLE();
+ }
+
+ return 0;
+}
+
+int VariableColumnCount(GLenum type)
+{
+ switch (type)
+ {
+ case GL_NONE:
+ return 0;
+ case GL_BOOL:
+ case GL_FLOAT:
+ case GL_INT:
+ return 1;
+ case GL_BOOL_VEC2:
+ case GL_FLOAT_VEC2:
+ case GL_INT_VEC2:
+ case GL_FLOAT_MAT2:
+ return 2;
+ case GL_INT_VEC3:
+ case GL_FLOAT_VEC3:
+ case GL_BOOL_VEC3:
+ case GL_FLOAT_MAT3:
+ return 3;
+ case GL_BOOL_VEC4:
+ case GL_FLOAT_VEC4:
+ case GL_INT_VEC4:
+ case GL_FLOAT_MAT4:
+ return 4;
+ default:
+ UNREACHABLE();
+ }
+
+ return 0;
+}
+
+int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
+{
+ ASSERT(allocationSize <= bitsSize);
+
+ unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
+
+ for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
+ {
+ if ((*bits & mask) == 0)
+ {
+ *bits |= mask;
+ return i;
+ }
+
+ mask <<= 1;
+ }
+
+ return -1;
+}
+
+GLsizei ComputePitch(GLsizei width, GLenum format, GLenum type, GLint alignment)
+{
+ ASSERT(alignment > 0 && isPow2(alignment));
+
+ GLsizei rawPitch = ComputePixelSize(format, type) * width;
+ return (rawPitch + alignment - 1) & ~(alignment - 1);
+}
+
+GLsizei ComputeCompressedPitch(GLsizei width, GLenum format)
+{
+ switch (format)
+ {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ break;
+ default:
+ return 0;
+ }
+
+ ASSERT(width % 4 == 0);
+
+ return 8 * width / 4;
+}
+
+GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format)
+{
+ switch (format)
+ {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ break;
+ default:
+ return 0;
+ }
+
+ return 8 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
+}
+
+bool IsCompressed(GLenum format)
+{
+ if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
+ format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Returns the size, in bytes, of a single texel in an Image
+int ComputePixelSize(GLenum format, GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ switch (format)
+ {
+ case GL_ALPHA: return sizeof(unsigned char);
+ case GL_LUMINANCE: return sizeof(unsigned char);
+ case GL_LUMINANCE_ALPHA: return sizeof(unsigned char) * 2;
+ case GL_RGB: return sizeof(unsigned char) * 3;
+ case GL_RGBA: return sizeof(unsigned char) * 4;
+ case GL_BGRA_EXT: return sizeof(unsigned char) * 4;
+ default: UNREACHABLE();
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT_5_6_5:
+ 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 IsTextureTarget(GLenum target)
+{
+ return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
+}
+
+// Verify that format/type are one of the combinations from table 3.4.
+bool CheckTextureFormatType(GLenum format, GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ switch (format)
+ {
+ case GL_RGBA:
+ case GL_BGRA_EXT:
+ case GL_RGB:
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ return true;
+
+ default:
+ return false;
+ }
+
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ return (format == GL_RGBA);
+
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return (format == GL_RGB);
+
+ 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;
+}
+
+DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha)
+{
+ return (red ? D3DCOLORWRITEENABLE_RED : 0) |
+ (green ? D3DCOLORWRITEENABLE_GREEN : 0) |
+ (blue ? D3DCOLORWRITEENABLE_BLUE : 0) |
+ (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0);
+}
+
+D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter)
+{
+ D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT;
+ switch (magFilter)
+ {
+ case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break;
+ case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dMagFilter;
+}
+
+void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter)
+{
+ switch (minFilter)
+ {
+ case GL_NEAREST:
+ *d3dMinFilter = D3DTEXF_POINT;
+ *d3dMipFilter = D3DTEXF_NONE;
+ break;
+ case GL_LINEAR:
+ *d3dMinFilter = D3DTEXF_LINEAR;
+ *d3dMipFilter = D3DTEXF_NONE;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ *d3dMinFilter = D3DTEXF_POINT;
+ *d3dMipFilter = D3DTEXF_POINT;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ *d3dMinFilter = D3DTEXF_LINEAR;
+ *d3dMipFilter = D3DTEXF_POINT;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ *d3dMinFilter = D3DTEXF_POINT;
+ *d3dMipFilter = D3DTEXF_LINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ *d3dMinFilter = D3DTEXF_LINEAR;
+ *d3dMipFilter = D3DTEXF_LINEAR;
+ break;
+ default:
+ *d3dMinFilter = D3DTEXF_POINT;
+ *d3dMipFilter = D3DTEXF_NONE;
+ UNREACHABLE();
+ }
+}
+
+unsigned int GetStencilSize(D3DFORMAT stencilFormat)
+{
+ switch(stencilFormat)
+ {
+ case D3DFMT_D24FS8:
+ case D3DFMT_D24S8:
+ return 8;
+ case D3DFMT_D24X4S4:
+ return 4;
+ case D3DFMT_D15S1:
+ return 1;
+ case D3DFMT_D16_LOCKABLE:
+ case D3DFMT_D32:
+ case D3DFMT_D24X8:
+ case D3DFMT_D32F_LOCKABLE:
+ case D3DFMT_D16:
+ return 0;
+// case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only
+// case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only
+ default: UNREACHABLE();
+ }
+ return 0;
+}
+
+unsigned int GetAlphaSize(D3DFORMAT colorFormat)
+{
+ switch (colorFormat)
+ {
+ case D3DFMT_A2R10G10B10:
+ return 2;
+ case D3DFMT_A8R8G8B8:
+ return 8;
+ case D3DFMT_A1R5G5B5:
+ return 1;
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_X1R5G5B5:
+ case D3DFMT_R5G6B5:
+ return 0;
+ default: UNREACHABLE();
+ }
+ return 0;
+}
+
+unsigned int GetRedSize(D3DFORMAT colorFormat)
+{
+ switch (colorFormat)
+ {
+ case D3DFMT_A2R10G10B10:
+ return 10;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ return 8;
+ case D3DFMT_A1R5G5B5:
+ case D3DFMT_R5G6B5:
+ case D3DFMT_X1R5G5B5:
+ return 5;
+ default: UNREACHABLE();
+ }
+ return 0;
+}
+
+unsigned int GetGreenSize(D3DFORMAT colorFormat)
+{
+ switch (colorFormat)
+ {
+ case D3DFMT_A2R10G10B10:
+ return 10;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ return 8;
+ case D3DFMT_A1R5G5B5:
+ case D3DFMT_X1R5G5B5:
+ return 5;
+ case D3DFMT_R5G6B5:
+ return 6;
+ default: UNREACHABLE();
+ }
+ return 0;
+}
+
+unsigned int GetBlueSize(D3DFORMAT colorFormat)
+{
+ switch (colorFormat)
+ {
+ case D3DFMT_A2R10G10B10:
+ return 10;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ return 8;
+ case D3DFMT_A1R5G5B5:
+ case D3DFMT_R5G6B5:
+ case D3DFMT_X1R5G5B5:
+ return 5;
+ default: UNREACHABLE();
+ }
+ return 0;
+}
+
+unsigned int GetDepthSize(D3DFORMAT depthFormat)
+{
+ switch (depthFormat)
+ {
+ case D3DFMT_D16_LOCKABLE: return 16;
+ case D3DFMT_D32: return 32;
+ case D3DFMT_D15S1: return 15;
+ case D3DFMT_D24S8: return 24;
+ case D3DFMT_D24X8: return 24;
+ case D3DFMT_D24X4S4: return 24;
+ case D3DFMT_D16: return 16;
+ case D3DFMT_D32F_LOCKABLE: return 32;
+ case D3DFMT_D24FS8: return 24;
+// case D3DFMT_D32_LOCKABLE: return 32; // D3D9Ex only
+// case D3DFMT_S8_LOCKABLE: return 0; // D3D9Ex only
+ default:
+ UNREACHABLE();
+ }
+ return 0;
+}
+
+bool ConvertPrimitiveType(GLenum primitiveType, GLsizei primitiveCount,
+ D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount)
+{
+ switch (primitiveType)
+ {
+ case GL_POINTS:
+ *d3dPrimitiveType = D3DPT_POINTLIST;
+ *d3dPrimitiveCount = primitiveCount;
+ break;
+ case GL_LINES:
+ *d3dPrimitiveType = D3DPT_LINELIST;
+ *d3dPrimitiveCount = primitiveCount / 2;
+ break;
+ case GL_LINE_LOOP:
+ *d3dPrimitiveType = D3DPT_LINESTRIP;
+ *d3dPrimitiveCount = primitiveCount;
+ break;
+ case GL_LINE_STRIP:
+ *d3dPrimitiveType = D3DPT_LINESTRIP;
+ *d3dPrimitiveCount = primitiveCount - 1;
+ break;
+ case GL_TRIANGLES:
+ *d3dPrimitiveType = D3DPT_TRIANGLELIST;
+ *d3dPrimitiveCount = primitiveCount / 3;
+ break;
+ case GL_TRIANGLE_STRIP:
+ *d3dPrimitiveType = D3DPT_TRIANGLESTRIP;
+ *d3dPrimitiveCount = primitiveCount - 2;
+ break;
+ case GL_TRIANGLE_FAN:
+ *d3dPrimitiveType = D3DPT_TRIANGLEFAN;
+ *d3dPrimitiveCount = primitiveCount - 2;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+D3DFORMAT ConvertRenderbufferFormat(GLenum format)
+{
+ switch (format)
+ {
+ 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;
+ }
+}
+
+GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
+{
+ if (type == D3DMULTISAMPLE_NONMASKABLE)
+ return 0;
+ else
+ return type;
+}
+
+D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples)
+{
+ if (samples <= 1)
+ return D3DMULTISAMPLE_NONE;
+ else
+ return (D3DMULTISAMPLE_TYPE)samples;
+}
+
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.h b/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.h
new file mode 100644
index 0000000..b6c8ce5
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.h
@@ -0,0 +1,68 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// 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>
+
+namespace gl
+{
+
+struct Color;
+
+int UniformComponentCount(GLenum type);
+GLenum UniformComponentType(GLenum type);
+size_t UniformTypeSize(GLenum type);
+int VariableRowCount(GLenum type);
+int VariableColumnCount(GLenum type);
+
+int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize);
+
+int ComputePixelSize(GLenum format, GLenum type);
+GLsizei ComputePitch(GLsizei width, GLenum format, GLenum type, GLint alignment);
+GLsizei ComputeCompressedPitch(GLsizei width, GLenum format);
+GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format);
+bool IsCompressed(GLenum format);
+bool IsCubemapTextureTarget(GLenum target);
+bool IsTextureTarget(GLenum target);
+bool CheckTextureFormatType(GLenum format, GLenum type);
+
+}
+
+namespace es2dx
+{
+
+D3DCMPFUNC ConvertComparison(GLenum comparison);
+D3DCOLOR ConvertColor(gl::Color color);
+D3DBLEND ConvertBlendFunc(GLenum blend);
+D3DBLENDOP ConvertBlendOp(GLenum blendOp);
+D3DSTENCILOP ConvertStencilOp(GLenum stencilOp);
+D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap);
+D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace);
+DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha);
+D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter);
+void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter);
+unsigned int GetAlphaSize(D3DFORMAT colorFormat);
+unsigned int GetRedSize(D3DFORMAT colorFormat);
+unsigned int GetGreenSize(D3DFORMAT colorFormat);
+unsigned int GetBlueSize(D3DFORMAT colorFormat);
+unsigned int GetDepthSize(D3DFORMAT depthFormat);
+unsigned int GetStencilSize(D3DFORMAT stencilFormat);
+bool ConvertPrimitiveType(GLenum primitiveType, GLsizei primitiveCount,
+ D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount);
+D3DFORMAT ConvertRenderbufferFormat(GLenum format);
+D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples);
+GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type);
+
+}
+
+#endif // LIBGLESV2_UTILITIES_H
diff --git a/Source/ThirdParty/Makefile b/Source/ThirdParty/Makefile
new file mode 100644
index 0000000..d9b8d2a
--- /dev/null
+++ b/Source/ThirdParty/Makefile
@@ -0,0 +1,17 @@
+MODULES = ANGLE
+
+all:
+ @for dir in $(MODULES); do ${MAKE} $@ -C $$dir; exit_status=$$?; \
+ if [ $$exit_status -ne 0 ]; then exit $$exit_status; fi; done
+
+debug d development dev develop:
+ @for dir in $(MODULES); do ${MAKE} $@ -C $$dir; exit_status=$$?; \
+ if [ $$exit_status -ne 0 ]; then exit $$exit_status; fi; done
+
+release r deployment dep deploy:
+ @for dir in $(MODULES); do ${MAKE} $@ -C $$dir; exit_status=$$?; \
+ if [ $$exit_status -ne 0 ]; then exit $$exit_status; fi; done
+
+clean:
+ @for dir in $(MODULES); do ${MAKE} $@ -C $$dir; exit_status=$$?; \
+ if [ $$exit_status -ne 0 ]; then exit $$exit_status; fi; done
diff --git a/Source/ThirdParty/Makefile.shared b/Source/ThirdParty/Makefile.shared
new file mode 100644
index 0000000..1c78613
--- /dev/null
+++ b/Source/ThirdParty/Makefile.shared
@@ -0,0 +1,2 @@
+SCRIPTS_PATH ?= ../../../Tools/Scripts
+include ../../../Makefile.shared