diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-01-06 14:44:00 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-01-06 14:44:00 +0100 |
commit | 40736c5763bf61337c8c14e16d8587db021a87d4 (patch) | |
tree | b17a9c00042ad89cb1308e2484491799aa14e9f8 /Source/ThirdParty/ANGLE | |
download | qtwebkit-40736c5763bf61337c8c14e16d8587db021a87d4.tar.gz |
Imported WebKit commit 2ea9d364d0f6efa8fa64acf19f451504c59be0e4 (http://svn.webkit.org/repository/webkit/trunk@104285)
Diffstat (limited to 'Source/ThirdParty/ANGLE')
173 files changed, 64551 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 000000000..8e80ad78e --- /dev/null +++ b/Source/ThirdParty/ANGLE/ANGLE.xcodeproj/project.pbxproj @@ -0,0 +1,662 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 90D9B10212E11DCB002D4255 /* Compiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90D9B0F912E11DCB002D4255 /* Compiler.cpp */; }; + 90D9B10312E11DCB002D4255 /* ExtensionBehavior.h in Headers */ = {isa = PBXBuildFile; fileRef = 90D9B0FA12E11DCB002D4255 /* ExtensionBehavior.h */; }; + 90D9B10412E11DCB002D4255 /* glslang_lex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90D9B0FB12E11DCB002D4255 /* glslang_lex.cpp */; }; + 90D9B10512E11DCB002D4255 /* glslang_tab.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90D9B0FC12E11DCB002D4255 /* glslang_tab.cpp */; }; + 90D9B10612E11DCB002D4255 /* glslang_tab.h in Headers */ = {isa = PBXBuildFile; fileRef = 90D9B0FD12E11DCB002D4255 /* glslang_tab.h */; }; + 90D9B10712E11DCB002D4255 /* glslang.h in Headers */ = {isa = PBXBuildFile; fileRef = 90D9B0FE12E11DCB002D4255 /* glslang.h */; }; + 90D9B10912E11DCB002D4255 /* SearchSymbol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90D9B10012E11DCB002D4255 /* SearchSymbol.cpp */; }; + 90D9B10A12E11DCB002D4255 /* SearchSymbol.h in Headers */ = {isa = PBXBuildFile; fileRef = 90D9B10112E11DCB002D4255 /* SearchSymbol.h */; }; + 90D9B11312E11DD6002D4255 /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90D9B10B12E11DD6002D4255 /* util.cpp */; }; + 90D9B11412E11DD6002D4255 /* util.h in Headers */ = {isa = PBXBuildFile; fileRef = 90D9B10C12E11DD6002D4255 /* util.h */; }; + 90D9B11512E11DD6002D4255 /* ValidateLimitations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90D9B10D12E11DD6002D4255 /* ValidateLimitations.cpp */; }; + 90D9B11612E11DD6002D4255 /* ValidateLimitations.h in Headers */ = {isa = PBXBuildFile; fileRef = 90D9B10E12E11DD6002D4255 /* ValidateLimitations.h */; }; + 90D9B11712E11DD6002D4255 /* VariableInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90D9B10F12E11DD6002D4255 /* VariableInfo.cpp */; }; + 90D9B11812E11DD6002D4255 /* VariableInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 90D9B11012E11DD6002D4255 /* VariableInfo.h */; }; + 90D9B11912E11DD6002D4255 /* VersionGLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90D9B11112E11DD6002D4255 /* VersionGLSL.cpp */; }; + 90D9B11A12E11DD6002D4255 /* VersionGLSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 90D9B11212E11DD6002D4255 /* VersionGLSL.h */; }; + A0AABE2C13AFE81000F2EBD1 /* ForLoopUnroll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A0AABE2A13AFE81000F2EBD1 /* ForLoopUnroll.cpp */; }; + A0AABE2D13AFE81000F2EBD1 /* ForLoopUnroll.h in Headers */ = {isa = PBXBuildFile; fileRef = A0AABE2B13AFE81000F2EBD1 /* ForLoopUnroll.h */; }; + A0AABE3013AFE83000F2EBD1 /* MapLongVariableNames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A0AABE2E13AFE83000F2EBD1 /* MapLongVariableNames.cpp */; }; + A0AABE3113AFE83000F2EBD1 /* MapLongVariableNames.h in Headers */ = {isa = PBXBuildFile; fileRef = A0AABE2F13AFE83000F2EBD1 /* MapLongVariableNames.h */; }; + A0AABE3413AFE84700F2EBD1 /* OutputGLSLBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A0AABE3213AFE84700F2EBD1 /* OutputGLSLBase.cpp */; }; + A0AABE3513AFE84700F2EBD1 /* OutputGLSLBase.h in Headers */ = {isa = PBXBuildFile; fileRef = A0AABE3313AFE84700F2EBD1 /* OutputGLSLBase.h */; }; + A0AABE4413AFE94500F2EBD1 /* OutputESSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A0AABE4213AFE94500F2EBD1 /* OutputESSL.cpp */; }; + A0AABE4513AFE94500F2EBD1 /* OutputESSL.h in Headers */ = {isa = PBXBuildFile; fileRef = A0AABE4313AFE94500F2EBD1 /* OutputESSL.h */; }; + A0AABE4813AFE96100F2EBD1 /* TranslatorESSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A0AABE4613AFE96100F2EBD1 /* TranslatorESSL.cpp */; }; + A0AABE4913AFE96100F2EBD1 /* TranslatorESSL.h in Headers */ = {isa = PBXBuildFile; fileRef = A0AABE4713AFE96100F2EBD1 /* TranslatorESSL.h */; }; + 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 */; }; + 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>"; }; + 90D9B0F912E11DCB002D4255 /* Compiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Compiler.cpp; sourceTree = "<group>"; }; + 90D9B0FA12E11DCB002D4255 /* ExtensionBehavior.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExtensionBehavior.h; sourceTree = "<group>"; }; + 90D9B0FB12E11DCB002D4255 /* glslang_lex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = glslang_lex.cpp; sourceTree = "<group>"; }; + 90D9B0FC12E11DCB002D4255 /* glslang_tab.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = glslang_tab.cpp; sourceTree = "<group>"; }; + 90D9B0FD12E11DCB002D4255 /* glslang_tab.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glslang_tab.h; sourceTree = "<group>"; }; + 90D9B0FE12E11DCB002D4255 /* glslang.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glslang.h; sourceTree = "<group>"; }; + 90D9B0FF12E11DCB002D4255 /* ossource_nspr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossource_nspr.cpp; sourceTree = "<group>"; }; + 90D9B10012E11DCB002D4255 /* SearchSymbol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SearchSymbol.cpp; sourceTree = "<group>"; }; + 90D9B10112E11DCB002D4255 /* SearchSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SearchSymbol.h; sourceTree = "<group>"; }; + 90D9B10B12E11DD6002D4255 /* util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = util.cpp; sourceTree = "<group>"; }; + 90D9B10C12E11DD6002D4255 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util.h; sourceTree = "<group>"; }; + 90D9B10D12E11DD6002D4255 /* ValidateLimitations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ValidateLimitations.cpp; sourceTree = "<group>"; }; + 90D9B10E12E11DD6002D4255 /* ValidateLimitations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValidateLimitations.h; sourceTree = "<group>"; }; + 90D9B10F12E11DD6002D4255 /* VariableInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VariableInfo.cpp; sourceTree = "<group>"; }; + 90D9B11012E11DD6002D4255 /* VariableInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VariableInfo.h; sourceTree = "<group>"; }; + 90D9B11112E11DD6002D4255 /* VersionGLSL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VersionGLSL.cpp; sourceTree = "<group>"; }; + 90D9B11212E11DD6002D4255 /* VersionGLSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VersionGLSL.h; sourceTree = "<group>"; }; + A0AABE2A13AFE81000F2EBD1 /* ForLoopUnroll.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ForLoopUnroll.cpp; sourceTree = "<group>"; }; + A0AABE2B13AFE81000F2EBD1 /* ForLoopUnroll.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ForLoopUnroll.h; sourceTree = "<group>"; }; + A0AABE2E13AFE83000F2EBD1 /* MapLongVariableNames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MapLongVariableNames.cpp; sourceTree = "<group>"; }; + A0AABE2F13AFE83000F2EBD1 /* MapLongVariableNames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapLongVariableNames.h; sourceTree = "<group>"; }; + A0AABE3213AFE84700F2EBD1 /* OutputGLSLBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OutputGLSLBase.cpp; sourceTree = "<group>"; }; + A0AABE3313AFE84700F2EBD1 /* OutputGLSLBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OutputGLSLBase.h; sourceTree = "<group>"; }; + A0AABE4213AFE94500F2EBD1 /* OutputESSL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OutputESSL.cpp; sourceTree = "<group>"; }; + A0AABE4313AFE94500F2EBD1 /* OutputESSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OutputESSL.h; sourceTree = "<group>"; }; + A0AABE4613AFE96100F2EBD1 /* TranslatorESSL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TranslatorESSL.cpp; sourceTree = "<group>"; }; + A0AABE4713AFE96100F2EBD1 /* TranslatorESSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TranslatorESSL.h; 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>"; }; + 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>"; }; + 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>"; }; + 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>"; }; + FB39D2BF1200F3E600088E69 /* ShaderLang.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = ShaderLang.h; sourceTree = "<group>"; }; +/* 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 */, + 5D7C59C41208C68B001C873E /* Configurations */, + FB39D0CC1200EF9B00088E69 /* Products */, + ); + sourceTree = "<group>"; + }; + FB39D0841200EDEB00088E69 /* Source */ = { + isa = PBXGroup; + children = ( + FB39D2BD1200F3E600088E69 /* GLSLANG */, + FB39D1851200F26200088E69 /* compiler */, + ); + name = Source; + 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 */, + 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 */, + ); + 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 = ( + A0AABE3213AFE84700F2EBD1 /* OutputGLSLBase.cpp */, + A0AABE3313AFE84700F2EBD1 /* OutputGLSLBase.h */, + A0AABE4613AFE96100F2EBD1 /* TranslatorESSL.cpp */, + A0AABE4713AFE96100F2EBD1 /* TranslatorESSL.h */, + A0AABE4213AFE94500F2EBD1 /* OutputESSL.cpp */, + A0AABE4313AFE94500F2EBD1 /* OutputESSL.h */, + A0AABE2E13AFE83000F2EBD1 /* MapLongVariableNames.cpp */, + A0AABE2F13AFE83000F2EBD1 /* MapLongVariableNames.h */, + A0AABE2A13AFE81000F2EBD1 /* ForLoopUnroll.cpp */, + A0AABE2B13AFE81000F2EBD1 /* ForLoopUnroll.h */, + FB39D2441200F35A00088E69 /* preprocessor */, + FB39D2211200F35A00088E69 /* BaseTypes.h */, + FB39D2221200F35A00088E69 /* CodeGenGLSL.cpp */, + FB39D2241200F35A00088E69 /* Common.h */, + 90D9B0F912E11DCB002D4255 /* Compiler.cpp */, + FB39D2251200F35A00088E69 /* ConstantUnion.h */, + FB39D2261200F35A00088E69 /* debug.cpp */, + FB39D2271200F35A00088E69 /* debug.h */, + 90D9B0FA12E11DCB002D4255 /* ExtensionBehavior.h */, + 90D9B0FB12E11DCB002D4255 /* glslang_lex.cpp */, + 90D9B0FC12E11DCB002D4255 /* glslang_tab.cpp */, + 90D9B0FD12E11DCB002D4255 /* glslang_tab.h */, + 90D9B0FE12E11DCB002D4255 /* glslang.h */, + 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 */, + 90D9B0FF12E11DCB002D4255 /* ossource_nspr.cpp */, + 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 */, + FB39D2561200F35A00088E69 /* QualifierAlive.cpp */, + FB39D2571200F35A00088E69 /* QualifierAlive.h */, + FB39D2581200F35A00088E69 /* RemoveTree.cpp */, + FB39D2591200F35A00088E69 /* RemoveTree.h */, + 90D9B10012E11DCB002D4255 /* SearchSymbol.cpp */, + 90D9B10112E11DCB002D4255 /* SearchSymbol.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 */, + 90D9B10B12E11DD6002D4255 /* util.cpp */, + 90D9B10C12E11DD6002D4255 /* util.h */, + 90D9B10D12E11DD6002D4255 /* ValidateLimitations.cpp */, + 90D9B10E12E11DD6002D4255 /* ValidateLimitations.h */, + 90D9B10F12E11DD6002D4255 /* VariableInfo.cpp */, + 90D9B11012E11DD6002D4255 /* VariableInfo.h */, + 90D9B11112E11DD6002D4255 /* VersionGLSL.cpp */, + 90D9B11212E11DD6002D4255 /* VersionGLSL.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 */, + 90D9B10312E11DCB002D4255 /* ExtensionBehavior.h in Headers */, + 90D9B10612E11DCB002D4255 /* glslang_tab.h in Headers */, + 90D9B10712E11DCB002D4255 /* glslang.h in Headers */, + 90D9B10A12E11DCB002D4255 /* SearchSymbol.h in Headers */, + 90D9B11412E11DD6002D4255 /* util.h in Headers */, + 90D9B11612E11DD6002D4255 /* ValidateLimitations.h in Headers */, + 90D9B11812E11DD6002D4255 /* VariableInfo.h in Headers */, + 90D9B11A12E11DD6002D4255 /* VersionGLSL.h in Headers */, + A0AABE2D13AFE81000F2EBD1 /* ForLoopUnroll.h in Headers */, + A0AABE3113AFE83000F2EBD1 /* MapLongVariableNames.h in Headers */, + A0AABE3513AFE84700F2EBD1 /* OutputGLSLBase.h in Headers */, + A0AABE4513AFE94500F2EBD1 /* OutputESSL.h in Headers */, + A0AABE4913AFE96100F2EBD1 /* TranslatorESSL.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 */, + 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; + attributes = { + LastUpgradeCheck = 0440; + }; + buildConfigurationList = FB39D0731200ED9200088E69 /* Build configuration list for PBXProject "ANGLE" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = FB39D06E1200ED9200088E69; + projectDirPath = ""; + projectRoot = ""; + targets = ( + FB39D0D01200F0E300088E69 /* ANGLE */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + FB39D0CE1200F0E300088E69 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 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 */, + 90D9B10212E11DCB002D4255 /* Compiler.cpp in Sources */, + 90D9B10412E11DCB002D4255 /* glslang_lex.cpp in Sources */, + 90D9B10512E11DCB002D4255 /* glslang_tab.cpp in Sources */, + 90D9B10912E11DCB002D4255 /* SearchSymbol.cpp in Sources */, + 90D9B11312E11DD6002D4255 /* util.cpp in Sources */, + 90D9B11512E11DD6002D4255 /* ValidateLimitations.cpp in Sources */, + 90D9B11712E11DD6002D4255 /* VariableInfo.cpp in Sources */, + 90D9B11912E11DD6002D4255 /* VersionGLSL.cpp in Sources */, + A0AABE2C13AFE81000F2EBD1 /* ForLoopUnroll.cpp in Sources */, + A0AABE3013AFE83000F2EBD1 /* MapLongVariableNames.cpp in Sources */, + A0AABE3413AFE84700F2EBD1 /* OutputGLSLBase.cpp in Sources */, + A0AABE4413AFE94500F2EBD1 /* OutputESSL.cpp in Sources */, + A0AABE4813AFE96100F2EBD1 /* TranslatorESSL.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 000000000..ec1171579 --- /dev/null +++ b/Source/ThirdParty/ANGLE/ChangeLog @@ -0,0 +1,1914 @@ +2011-11-11 Darin Adler <darin@apple.com> + + * ANGLE.xcodeproj/project.pbxproj: Let a newer Xcode update this file. + If an older Xcode downgrades this file and we have a risk of some kind of + oscillating commit situation, please contact me so I know not to do this again. + +2011-09-19 Adam Roben <aroben@apple.com> + + Let Xcode 4 do its thang with ANGLE.xcodeproj + + * ANGLE.xcodeproj/project.pbxproj: + +2011-09-13 Anders Carlsson <andersca@apple.com> + + Disable C++ exceptions when building with clang + https://bugs.webkit.org/show_bug.cgi?id=68031 + <rdar://problem/9556880> + + Reviewed by Mark Rowe. + + * Configurations/Base.xcconfig: + +2011-09-08 Andras Becsi <andras.becsi@nokia.com> + + [Qt] Build fails with strict compiler + https://bugs.webkit.org/show_bug.cgi?id=67778 + + Reviewed by Csaba Osztrogonác. + + * src/compiler/glslang_lex.cpp: Regenerate with generate_glslang_lexer.sh using a newer flex + to suppress warning and fix the build when using [-Werror=unused-result] + +2011-08-12 Mark Rowe <mrowe@apple.com> + + Be more forward-looking in the choice of compiler. + + Rubber-stamped by Jon Honeycutt. + + * Configurations/CompilerVersion.xcconfig: + +2011-08-11 Renata Hodovan <reni@webkit.org> + + [Qt]Fix warnings after r92805. + + Reviewed by Csaba Osztrogonác. + + Control reached the end non-void functions. + + * src/compiler/ossource_posix.cpp: + (OS_AllocTLSIndex): + (OS_SetTLSValue): + +2011-08-11 Renata Hodovan <reni@webkit.org> + + Build fix on Qt Windows 32-bit Release/Debug after r92805. + + Unreviewed. + + * src/compiler/ossource_posix.cpp: + (OS_FreeTLSIndex): + +2011-08-04 Mark Rowe <mrowe@apple.com> + + Future-proof Xcode configuration settings. + + * Configurations/Base.xcconfig: + * Configurations/CompilerVersion.xcconfig: + * Configurations/DebugRelease.xcconfig: + +2011-06-30 Mark Rowe <mrowe@apple.com> + + Rubber-stamped by Dan Bernstein. + + ANGLE shouldn't try to use internal SDKs. It doesn't need them! + + * Configurations/Base.xcconfig: + +2011-06-20 Zhenyao Mo <zmo@google.com> + + Reviewed by Kenneth Russell. + + Update ANGLE to r696 + https://bugs.webkit.org/show_bug.cgi?id=56396 + + * ANGLE.xcodeproj/project.pbxproj: + * include/EGL/eglext.h: + * include/GLSLANG/ShaderLang.h: + * src/build_angle.xcodeproj/project.pbxproj: + * src/common/debug.cpp: + (gl::output): + (gl::trace): + (gl::perfActive): + (gl::ScopedPerfEventHelper::ScopedPerfEventHelper): + (gl::ScopedPerfEventHelper::~ScopedPerfEventHelper): + * src/common/debug.h: + * src/common/version.h: Added. + * src/compiler/CodeGenGLSL.cpp: + (ConstructCompiler): + * src/compiler/CodeGenHLSL.cpp: + (ConstructCompiler): + * src/compiler/Compiler.cpp: + (TCompiler::compile): + (TCompiler::mapLongVariableNames): + (TCompiler::getMappedNameMaxLength): + (TCompiler::getExtensionBehavior): + * src/compiler/ConstantUnion.h: + (ConstantUnion::operator==): + (ConstantUnion::operator>): + (ConstantUnion::operator<): + * src/compiler/ExtensionBehavior.h: + (getBehaviorString): + * src/compiler/ForLoopUnroll.cpp: Added. + (ForLoopUnroll::FillLoopIndexInfo): + (ForLoopUnroll::Step): + (ForLoopUnroll::SatisfiesLoopCondition): + (ForLoopUnroll::NeedsToReplaceSymbolWithValue): + (ForLoopUnroll::GetLoopIndexValue): + (ForLoopUnroll::Push): + (ForLoopUnroll::Pop): + (ForLoopUnroll::getLoopIncrement): + (ForLoopUnroll::evaluateIntConstant): + * src/compiler/ForLoopUnroll.h: Added. + (ForLoopUnroll::ForLoopUnroll): + * src/compiler/Initialize.cpp: + (BuiltInFunctionsVertex): + * src/compiler/MapLongVariableNames.cpp: Added. + (MapLongVariableNames::MapLongVariableNames): + (MapLongVariableNames::visitSymbol): + (MapLongVariableNames::visitConstantUnion): + (MapLongVariableNames::visitBinary): + (MapLongVariableNames::visitUnary): + (MapLongVariableNames::visitSelection): + (MapLongVariableNames::visitAggregate): + (MapLongVariableNames::visitLoop): + (MapLongVariableNames::visitBranch): + (MapLongVariableNames::mapVaryingLongName): + * src/compiler/MapLongVariableNames.h: Added. + * src/compiler/OutputESSL.cpp: Added. + (TOutputESSL::TOutputESSL): + (TOutputESSL::writeVariablePrecision): + * src/compiler/OutputESSL.h: Added. + * src/compiler/OutputGLSL.cpp: + (TOutputGLSL::TOutputGLSL): + (TOutputGLSL::writeVariablePrecision): + * src/compiler/OutputGLSL.h: + * src/compiler/OutputGLSLBase.cpp: Added. + (TOutputGLSLBase::TOutputGLSLBase): + (TOutputGLSLBase::writeTriplet): + (TOutputGLSLBase::writeVariableType): + (TOutputGLSLBase::writeFunctionParameters): + (TOutputGLSLBase::writeConstantUnion): + (TOutputGLSLBase::visitSymbol): + (TOutputGLSLBase::visitConstantUnion): + (TOutputGLSLBase::visitBinary): + (TOutputGLSLBase::visitUnary): + (TOutputGLSLBase::visitSelection): + (TOutputGLSLBase::visitAggregate): + (TOutputGLSLBase::visitLoop): + (TOutputGLSLBase::visitBranch): + (TOutputGLSLBase::visitCodeBlock): + * src/compiler/OutputGLSLBase.h: Added. + (TOutputGLSLBase::objSink): + * src/compiler/OutputHLSL.cpp: + (sh::OutputHLSL::OutputHLSL): + (sh::OutputHLSL::header): + (sh::OutputHLSL::visitUnary): + (sh::OutputHLSL::visitAggregate): + (sh::OutputHLSL::visitSelection): + (sh::OutputHLSL::visitLoop): + (sh::OutputHLSL::visitBranch): + (sh::OutputHLSL::handleExcessiveLoop): + (sh::OutputHLSL::outputLineDirective): + * src/compiler/OutputHLSL.h: + * src/compiler/ParseHelper.cpp: + (TParseContext::precisionErrorCheck): + (TParseContext::constructorErrorCheck): + (TParseContext::nonInitErrorCheck): + * src/compiler/ParseHelper.h: + (TParseContext::TParseContext): + * src/compiler/ShHandle.h: + * src/compiler/ShaderLang.cpp: + (getVariableInfo): + (ShConstructCompiler): + (ShGetInfo): + (ShGetActiveAttrib): + (ShGetActiveUniform): + * src/compiler/TranslatorESSL.cpp: Added. + (TranslatorESSL::TranslatorESSL): + (TranslatorESSL::translate): + (TranslatorESSL::writeExtensionBehavior): + * src/compiler/TranslatorESSL.h: Added. + * src/compiler/ValidateLimitations.cpp: + (ValidateLimitations::visitBinary): + (ValidateLimitations::visitLoop): + * src/compiler/ValidateLimitations.h: + * src/compiler/VariableInfo.cpp: + (getVariableInfo): + (getBuiltInVariableInfo): + (getUserDefinedVariableInfo): + (CollectAttribsUniforms::visitAggregate): + * src/compiler/VariableInfo.h: + * src/compiler/VersionGLSL.cpp: + (TVersionGLSL::visitSymbol): + (TVersionGLSL::visitConstantUnion): + (TVersionGLSL::visitBinary): + (TVersionGLSL::visitUnary): + (TVersionGLSL::visitSelection): + (TVersionGLSL::visitAggregate): + (TVersionGLSL::visitLoop): + (TVersionGLSL::visitBranch): + * src/compiler/VersionGLSL.h: + * src/compiler/glslang.y: + * src/compiler/glslang_tab.cpp: + * src/compiler/glslang_tab.h: + * src/compiler/intermediate.h: + (TIntermLoop::TIntermLoop): + (TIntermLoop::setUnrollFlag): + (TIntermLoop::getUnrollFlag): + (TIntermSymbol::TIntermSymbol): + (TIntermSymbol::setId): + (TIntermSymbol::setSymbol): + (TIntermSymbol::getOriginalSymbol): + (TIntermAggregate::TIntermAggregate): + (TIntermAggregate::setEndLine): + (TIntermAggregate::getEndLine): + * src/compiler/preprocessor/atom.c: + (AddString): + * src/compiler/preprocessor/compile.h: + * src/compiler/preprocessor/cpp.c: + (CPPelse): + (eval): + (CPPif): + (CPPifdef): + (readCPPline): + (ChkCorrectElseNesting): + * src/compiler/preprocessor/cppstruct.c: + (ResetPreprocessor): + * src/compiler/preprocessor/scanner.c: + (byte_scan): + (yylex_CPP): + * src/compiler/preprocessor/scanner.h: + * src/libEGL/Config.cpp: + (egl::Config::Config): + (egl::Config::set): + (egl::ConfigSet::add): + (egl::ConfigSet::getConfigs): + * src/libEGL/Config.h: + * src/libEGL/Display.cpp: + (egl::Display::Display): + (egl::Display::initialize): + (egl::Display::terminate): + (egl::Display::getConfigAttrib): + (egl::Display::createDevice): + (egl::Display::createWindowSurface): + (egl::Display::createOffscreenSurface): + (egl::Display::createContext): + (egl::Display::destroyContext): + (egl::Display::isInitialized): + (egl::Display::getAdapterIdentifier): + (egl::Display::isDeviceLost): + (egl::Display::getBufferPool): + (egl::Display::initExtensionString): + (egl::Display::getExtensionString): + (egl::Display::getVertexTextureSupport): + (egl::Display::getNonPower2TextureSupport): + * src/libEGL/Display.h: + (egl::Display::isD3d9ExDevice): + * src/libEGL/Surface.cpp: + (egl::Surface::Surface): + (egl::Surface::initialize): + (egl::Surface::release): + (egl::Surface::resetSwapChain): + (egl::SurfaceWindowProc): + (egl::Surface::subclassWindow): + (egl::Surface::unsubclassWindow): + (egl::Surface::swap): + (egl::Surface::getRenderTarget): + (egl::Surface::getOffscreenTexture): + (egl::Surface::getTextureFormat): + (egl::Surface::getTextureTarget): + (egl::Surface::setBoundTexture): + (egl::Surface::getBoundTexture): + (egl::Surface::getFormat): + * src/libEGL/Surface.h: + (egl::Surface::getShareHandle): + * src/libEGL/libEGL.cpp: + (validateDisplay): + (validateConfig): + (validateContext): + (validateSurface): + * src/libEGL/libEGL.rc: Added. + * src/libEGL/libEGL.vcproj: + * src/libEGL/main.cpp: + (DllMain): + * src/libEGL/main.h: + * src/libEGL/resource.h: Added. + * src/libGLESv2/Blit.cpp: + (gl::Blit::initGeometry): + (gl::Blit::copy): + * src/libGLESv2/Blit.h: + * src/libGLESv2/Buffer.cpp: + (gl::Buffer::Buffer): + (gl::Buffer::~Buffer): + (gl::Buffer::bufferData): + (gl::Buffer::bufferSubData): + (gl::Buffer::getStaticVertexBuffer): + (gl::Buffer::getStaticIndexBuffer): + (gl::Buffer::invalidateStaticData): + (gl::Buffer::promoteStaticUsage): + * src/libGLESv2/Buffer.h: + * src/libGLESv2/Context.cpp: + (gl::Context::Context): + (gl::Context::~Context): + (gl::Context::makeCurrent): + (gl::Context::markAllStateDirty): + (gl::Context::setActiveSampler): + (gl::Context::createFramebuffer): + (gl::Context::createFence): + (gl::Context::deleteFramebuffer): + (gl::Context::deleteFence): + (gl::Context::bindTexture2D): + (gl::Context::bindTextureCubeMap): + (gl::Context::getTexture2D): + (gl::Context::getTextureCubeMap): + (gl::Context::getSamplerTexture): + (gl::Context::getIntegerv): + (gl::Context::applyRenderTarget): + (gl::Context::applyState): + (gl::Context::applyVertexBuffer): + (gl::Context::applyShaders): + (gl::Context::applyTextures): + (gl::Context::readPixels): + (gl::Context::clear): + (gl::Context::drawArrays): + (gl::Context::drawElements): + (gl::Context::finish): + (gl::Context::flush): + (gl::Context::drawClosingLine): + (gl::Context::getMaximumVertexTextureImageUnits): + (gl::Context::getMaximumCombinedTextureImageUnits): + (gl::Context::supportsNonPower2Texture): + (gl::Context::detachTexture): + (gl::Context::getIncompleteTexture): + (gl::Context::initExtensionString): + (gl::Context::blitFramebuffer): + (gl::VertexDeclarationCache::VertexDeclarationCache): + (gl::VertexDeclarationCache::~VertexDeclarationCache): + (gl::VertexDeclarationCache::applyDeclaration): + * src/libGLESv2/Context.h: + * src/libGLESv2/Framebuffer.cpp: + (gl::Framebuffer::lookupRenderbuffer): + (gl::Framebuffer::completeness): + * src/libGLESv2/Framebuffer.h: + * src/libGLESv2/HandleAllocator.cpp: Added. + (gl::HandleAllocator::HandleAllocator): + (gl::HandleAllocator::~HandleAllocator): + (gl::HandleAllocator::setBaseHandle): + (gl::HandleAllocator::allocate): + (gl::HandleAllocator::release): + * src/libGLESv2/HandleAllocator.h: Added. + * src/libGLESv2/IndexDataManager.cpp: Added. + (gl::IndexDataManager::IndexDataManager): + (gl::IndexDataManager::~IndexDataManager): + (gl::convertIndices): + (gl::computeRange): + (gl::IndexDataManager::prepareIndexData): + (gl::IndexDataManager::indexSize): + (gl::IndexDataManager::typeSize): + (gl::IndexBuffer::IndexBuffer): + (gl::IndexBuffer::~IndexBuffer): + (gl::IndexBuffer::getBuffer): + (gl::IndexBuffer::unmap): + (gl::StreamingIndexBuffer::StreamingIndexBuffer): + (gl::StreamingIndexBuffer::~StreamingIndexBuffer): + (gl::StreamingIndexBuffer::map): + (gl::StreamingIndexBuffer::reserveSpace): + (gl::StaticIndexBuffer::StaticIndexBuffer): + (gl::StaticIndexBuffer::~StaticIndexBuffer): + (gl::StaticIndexBuffer::map): + (gl::StaticIndexBuffer::reserveSpace): + (gl::StaticIndexBuffer::lookupType): + (gl::StaticIndexBuffer::lookupRange): + (gl::StaticIndexBuffer::addRange): + * src/libGLESv2/IndexDataManager.h: Added. + (gl::IndexBuffer::size): + * src/libGLESv2/Program.cpp: + (gl::Program::getSemanticIndex): + (gl::Program::getSamplerMapping): + (gl::Program::getSamplerTextureType): + (gl::Program::compileToBinary): + (gl::Program::packVaryings): + (gl::Program::linkVaryings): + (gl::Program::link): + (gl::Program::linkUniforms): + (gl::Program::defineUniform): + (gl::Program::applyUniform1iv): + (gl::Program::appendToInfoLogSanitized): + (gl::Program::unlink): + (gl::Program::getActiveUniformMaxLength): + (gl::Program::validate): + (gl::Program::validateSamplers): + * src/libGLESv2/Program.h: + * src/libGLESv2/Renderbuffer.cpp: + (gl::Renderbuffer::getWidth): + (gl::Renderbuffer::getHeight): + (gl::Renderbuffer::getInternalFormat): + (gl::Renderbuffer::getRedSize): + (gl::Renderbuffer::getGreenSize): + (gl::Renderbuffer::getBlueSize): + (gl::Renderbuffer::getAlphaSize): + (gl::Renderbuffer::getDepthSize): + (gl::Renderbuffer::getStencilSize): + (gl::Renderbuffer::getSamples): + (gl::RenderbufferStorage::RenderbufferStorage): + (gl::RenderbufferStorage::getWidth): + (gl::RenderbufferStorage::getHeight): + (gl::RenderbufferStorage::getInternalFormat): + (gl::RenderbufferStorage::getRedSize): + (gl::RenderbufferStorage::getGreenSize): + (gl::RenderbufferStorage::getBlueSize): + (gl::RenderbufferStorage::getAlphaSize): + (gl::RenderbufferStorage::getDepthSize): + (gl::RenderbufferStorage::getStencilSize): + (gl::RenderbufferStorage::getD3DFormat): + (gl::Colorbuffer::Colorbuffer): + (gl::Colorbuffer::getWidth): + (gl::Colorbuffer::getHeight): + (gl::Colorbuffer::getInternalFormat): + (gl::Colorbuffer::getType): + (gl::Colorbuffer::getD3DFormat): + (gl::Colorbuffer::isColorbuffer): + (gl::Colorbuffer::getRenderTarget): + (gl::DepthStencilbuffer::DepthStencilbuffer): + (gl::Depthbuffer::Depthbuffer): + (gl::Stencilbuffer::Stencilbuffer): + * src/libGLESv2/Renderbuffer.h: + * src/libGLESv2/ResourceManager.cpp: + (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::checkTextureAllocation): + * src/libGLESv2/ResourceManager.h: + * src/libGLESv2/Shader.cpp: + (gl::Shader::Shader): + (gl::Shader::compileToHLSL): + * src/libGLESv2/Shader.h: + * src/libGLESv2/Texture.cpp: + (gl::Texture::Image::Image): + (gl::Texture::Image::~Image): + (gl::Texture::Image::isRenderable): + (gl::Texture::Image::getD3DFormat): + (gl::Texture::Texture): + (gl::Texture::setMinFilter): + (gl::Texture::setMagFilter): + (gl::Texture::setWrapS): + (gl::Texture::setWrapT): + (gl::Texture::loadImageData): + (gl::Texture::loadAlphaImageData): + (gl::Texture::loadAlphaFloatImageData): + (gl::Texture::loadAlphaHalfFloatImageData): + (gl::Texture::loadLuminanceImageData): + (gl::Texture::loadLuminanceFloatImageData): + (gl::Texture::loadLuminanceHalfFloatImageData): + (gl::Texture::loadLuminanceAlphaImageData): + (gl::Texture::loadLuminanceAlphaFloatImageData): + (gl::Texture::loadLuminanceAlphaHalfFloatImageData): + (gl::Texture::loadRGBUByteImageData): + (gl::Texture::loadRGB565ImageData): + (gl::Texture::loadRGBFloatImageData): + (gl::Texture::loadRGBHalfFloatImageData): + (gl::Texture::loadRGBAUByteImageDataSSE2): + (gl::Texture::loadRGBAUByteImageData): + (gl::Texture::loadRGBA4444ImageData): + (gl::Texture::loadRGBA5551ImageData): + (gl::Texture::loadRGBAFloatImageData): + (gl::Texture::loadRGBAHalfFloatImageData): + (gl::Texture::loadBGRAImageData): + (gl::Texture::loadCompressedImageData): + (gl::Texture::createSurface): + (gl::Texture::setImage): + (gl::Texture::setCompressedImage): + (gl::Texture::subImage): + (gl::Texture::subImageCompressed): + (gl::Texture::copyToImage): + (gl::Texture::getTexture): + (gl::Texture::isDirtyParameter): + (gl::Texture::isDirtyImage): + (gl::Texture::resetDirty): + (gl::Texture::getSerial): + (gl::Texture::creationLevels): + (gl::Texture::levelCount): + (gl::Texture::issueSerial): + (gl::Texture2D::Texture2D): + (gl::Texture2D::~Texture2D): + (gl::Texture2D::getWidth): + (gl::Texture2D::getHeight): + (gl::Texture2D::getInternalFormat): + (gl::Texture2D::getType): + (gl::Texture2D::getD3DFormat): + (gl::Texture2D::redefineTexture): + (gl::Texture2D::setImage): + (gl::Texture2D::bindTexImage): + (gl::Texture2D::releaseTexImage): + (gl::Texture2D::setCompressedImage): + (gl::Texture2D::commitRect): + (gl::Texture2D::copyImage): + (gl::Texture2D::copySubImage): + (gl::Texture2D::isComplete): + (gl::Texture2D::isCompressed): + (gl::Texture2D::getBaseTexture): + (gl::Texture2D::createTexture): + (gl::Texture2D::updateTexture): + (gl::Texture2D::convertToRenderTarget): + (gl::Texture2D::generateMipmaps): + (gl::Texture2D::getRenderbuffer): + (gl::Texture2D::getRenderTarget): + (gl::TextureCubeMap::getWidth): + (gl::TextureCubeMap::getHeight): + (gl::TextureCubeMap::getInternalFormat): + (gl::TextureCubeMap::getType): + (gl::TextureCubeMap::getD3DFormat): + (gl::TextureCubeMap::setImagePosX): + (gl::TextureCubeMap::setImageNegX): + (gl::TextureCubeMap::setImagePosY): + (gl::TextureCubeMap::setImageNegY): + (gl::TextureCubeMap::setImagePosZ): + (gl::TextureCubeMap::setImageNegZ): + (gl::TextureCubeMap::setCompressedImage): + (gl::TextureCubeMap::commitRect): + (gl::TextureCubeMap::isComplete): + (gl::TextureCubeMap::isCompressed): + (gl::TextureCubeMap::getBaseTexture): + (gl::TextureCubeMap::createTexture): + (gl::TextureCubeMap::updateTexture): + (gl::TextureCubeMap::convertToRenderTarget): + (gl::TextureCubeMap::setImage): + (gl::TextureCubeMap::redefineTexture): + (gl::TextureCubeMap::copyImage): + (gl::TextureCubeMap::getCubeMapSurface): + (gl::TextureCubeMap::copySubImage): + (gl::TextureCubeMap::generateMipmaps): + (gl::TextureCubeMap::getRenderbuffer): + (gl::TextureCubeMap::getRenderTarget): + * src/libGLESv2/Texture.h: + * src/libGLESv2/VertexDataManager.cpp: Added. + (gl::VertexDataManager::VertexDataManager): + (gl::VertexDataManager::~VertexDataManager): + (gl::VertexDataManager::writeAttributeData): + (gl::VertexDataManager::prepareVertexData): + (gl::VertexDataManager::spaceRequired): + (gl::VertexDataManager::checkVertexCaps): + (gl::VertexDataManager::typeIndex): + (gl::VertexBuffer::VertexBuffer): + (gl::VertexBuffer::~VertexBuffer): + (gl::VertexBuffer::unmap): + (gl::VertexBuffer::getBuffer): + (gl::ConstantVertexBuffer::ConstantVertexBuffer): + (gl::ConstantVertexBuffer::~ConstantVertexBuffer): + (gl::ArrayVertexBuffer::ArrayVertexBuffer): + (gl::ArrayVertexBuffer::~ArrayVertexBuffer): + (gl::ArrayVertexBuffer::addRequiredSpace): + (gl::ArrayVertexBuffer::addRequiredSpaceFor): + (gl::StreamingVertexBuffer::StreamingVertexBuffer): + (gl::StreamingVertexBuffer::~StreamingVertexBuffer): + (gl::StreamingVertexBuffer::map): + (gl::StreamingVertexBuffer::reserveRequiredSpace): + (gl::StaticVertexBuffer::StaticVertexBuffer): + (gl::StaticVertexBuffer::~StaticVertexBuffer): + (gl::StaticVertexBuffer::map): + (gl::StaticVertexBuffer::reserveRequiredSpace): + (gl::StaticVertexBuffer::lookupAttribute): + (gl::VertexDataManager::formatConverter): + * src/libGLESv2/VertexDataManager.h: Added. + (gl::ArrayVertexBuffer::size): + (gl::VertexDataManager::dirtyCurrentValue): + * src/libGLESv2/libGLESv2.cpp: + (validImageSize): + (Extension::glBindTexImage): + * src/libGLESv2/libGLESv2.def: + * src/libGLESv2/libGLESv2.rc: Added. + * src/libGLESv2/libGLESv2.vcproj: + * src/libGLESv2/main.cpp: + (error): + * src/libGLESv2/mathutil.h: + (gl::clamp): + (gl::clamp01): + (gl::transformPixelRect): + (gl::transformPixelYOffset): + (gl::adjustWinding): + (gl::supportsSSE2): + * src/libGLESv2/resource.h: Added. + * src/libGLESv2/utilities.cpp: + (gl::ComputeCompressedPitch): + (es2dx::ConvertCubeFace): + (es2dx::ConvertPrimitiveType): + (es2dx::ConvertRenderbufferFormat): + (es2dx::GetMultisampleTypeFromSamples): + (dx2es::GetStencilSize): + (dx2es::GetAlphaSize): + (dx2es::GetRedSize): + (dx2es::GetGreenSize): + (dx2es::GetBlueSize): + (dx2es::GetDepthSize): + (getTempPath): + (writeFile): + * src/libGLESv2/utilities.h: + * src/libGLESv2/vertexconversion.h: Added. + (gl::Identity::convert): + (gl::Cast::convert): + (gl::Normalize::convert): + (gl::FixedToFloat::convert): + (gl::SimpleDefaultValues::zero): + (gl::SimpleDefaultValues::one): + (gl::NormalizedDefaultValues::zero): + (gl::NormalizedDefaultValues::one): + (gl::VertexDataConverter::convertArray): + (gl::VertexDataConverter::pointerAddBytes): + (gl::VertexDataConverter::copyComponent): + +2011-05-24 David Kilzer <ddkilzer@apple.com> + + Part 2 of 2: <http://webkit.org/b/60805> Enable -Wnewline-eof on ANGLE + + Reviewed by Adam Roben. + + * Configurations/Base.xcconfig: + (GCC_WARN_ABOUT_MISSING_NEWLINE): Added. Set to YES. + +2011-05-23 David Kilzer <ddkilzer@apple.com> + + Part 1 of 2: <http://webkit.org/b/60805> Enable -Wnewline-eof on ANGLE + + Merge ANGLE upstream commit r653 for Issue 154. + + * src/compiler/PoolAlloc.h: Added newline to end of file. + * src/compiler/ShHandle.h: Ditto. + * src/libEGL/Display.cpp: Ditto. + +2011-05-16 David Kilzer <ddkilzer@apple.com> + + <http://webkit.org/b/60913> C++ exceptions should not be enabled when building with llvm-gcc-4.2 + <rdar://problem/9446430> + + Reviewed by Mark Rowe. + + * Configurations/Base.xcconfig: Fixed typo. + +2011-05-04 David Kilzer <ddkilzer@apple.com> + + Part 2 of 2: <http://webkit.org/b/56337> Enable -Werror on ANGLE + + Reviewed by Adam Barth. + + * Configurations/Base.xcconfig: + (GCC_TREAT_WARNINGS_AS_ERRORS): Set to YES. + +2011-05-04 David Kilzer <ddkilzer@apple.com> + + Part 1 of 2: <http://webkit.org/b/56337> Enable -Werror on ANGLE + + Merge ANGLE upstream commits r572, r573, r574, r575. + + This unblocks enabling -Werror on ANGLE. Since all changes are + in the upstream repository, they may be safely overwritten + during the next ANGLE update. + + * src/compiler/ConstantUnion.h: + (ConstantUnion::operator==): Added a default case. + * src/compiler/Intermediate.cpp: + (TIntermBinary::promote): Added parentheses. + * src/compiler/ParseHelper.cpp: + (TParseContext::precisionErrorCheck): Added a default case. + * src/compiler/PoolAlloc.cpp: + (TAllocation::checkGuardBlock): Changed '%u' to '%lu' for size_t + variable. Put for loop inside #ifdef GUARD_BLOCKS/#endif macros + to fix tautological-compare warning. + (TAllocation::checkAllocList): Added newline to end of file. + +2011-04-26 Dan Bernstein <mitz@apple.com> + + Build fix. + + * Configurations/CompilerVersion.xcconfig: + +2011-04-26 Dan Bernstein <mitz@apple.com> + + Reviewed by Mark Rowe. + + Choose the compiler based on the Xcode version for Snow Leopard debug builds. + + * Configurations/Base.xcconfig: + * Configurations/CompilerVersion.xcconfig: Added. + +2011-03-17 Jeff Miller <jeffm@apple.com> + + Use a consistent set of file patterns in the svn:ignore property for all .xcodeproj directories, specifically: + + *.mode* + *.pbxuser + *.perspective* + project.xcworkspace + xcuserdata + + * ANGLE.xcodeproj: Modified property svn:ignore. + * src/build_angle.xcodeproj: Modified property svn:ignore. + +2011-01-18 Kenneth Russell <kbr@google.com> + + Unreviewed, Leopard build fix. Remove flex/bison targets for GLSL + grammar because the generated sources are already checked in. + + * ANGLE.xcodeproj/project.pbxproj: + * src/build_angle.xcodeproj/project.pbxproj: + +2011-01-18 Kenneth Russell <kbr@google.com> + + Unreviewed, release build fix. Explicitly cast away const. + + * src/compiler/preprocessor/scanner.c: + (ScanFromString): + +2011-01-18 Ben Vanik <ben.vanik@gmail.com> + + Reviewed by Kenneth Russell. + + Updating ANGLE in WebKit to r533. + https://bugs.webkit.org/show_bug.cgi?id=47194 + + * ANGLE.xcodeproj/project.pbxproj: + * include/GLSLANG/ShaderLang.h: + * src/common/debug.cpp: + (gl::trace): + * src/common/debug.h: + * src/compiler/CodeGenGLSL.cpp: + (ConstructCompiler): + * src/compiler/CodeGenHLSL.cpp: + (ConstructCompiler): + * src/compiler/Common.h: + (EncodeSourceLoc): + (DecodeSourceLoc): + * src/compiler/Compiler.cpp: Added. + (TShHandleBase::TShHandleBase): + (TShHandleBase::~TShHandleBase): + (TCompiler::TCompiler): + (TCompiler::~TCompiler): + (TCompiler::Init): + (TCompiler::compile): + (TCompiler::InitBuiltInSymbolTable): + (TCompiler::clearResults): + (TCompiler::validateLimitations): + (TCompiler::collectAttribsUniforms): + * src/compiler/ExtensionBehavior.h: Added. + * src/compiler/InfoSink.cpp: + (TInfoSinkBase::location): + * src/compiler/InfoSink.h: + (TInfoSinkBase::size): + * src/compiler/Initialize.cpp: + (BuiltInFunctionsCommon): + (BuiltInFunctionsVertex): + (BuiltInFunctionsFragment): + (StandardUniforms): + (DefaultPrecisionVertex): + (DefaultPrecisionFragment): + (BuiltInConstants): + (TBuiltIns::initialize): + (IdentifyBuiltIns): + (InitExtensionBehavior): + * src/compiler/Initialize.h: + * src/compiler/IntermTraverse.cpp: + (TIntermLoop::traverse): + * src/compiler/Intermediate.cpp: + (getOperatorString): + (TIntermediate::addBinaryMath): + (TIntermediate::addLoop): + (TIntermediate::postProcess): + (TIntermBinary::promote): + * src/compiler/OutputGLSL.cpp: + (TOutputGLSL::visitUnary): + (TOutputGLSL::visitLoop): + * src/compiler/OutputHLSL.cpp: + (sh::OutputHLSL::OutputHLSL): + (sh::OutputHLSL::header): + (sh::OutputHLSL::visitBinary): + (sh::OutputHLSL::visitUnary): + (sh::OutputHLSL::visitAggregate): + (sh::OutputHLSL::visitLoop): + (sh::OutputHLSL::handleExcessiveLoop): + (sh::OutputHLSL::argumentString): + * src/compiler/OutputHLSL.h: + * src/compiler/ParseHelper.cpp: + (ReportInfo): + (DefineExtensionMacros): + (TParseContext::error): + (TParseContext::warning): + (TParseContext::reservedErrorCheck): + (TParseContext::constructorErrorCheck): + (TParseContext::arrayQualifierErrorCheck): + (TParseContext::extensionErrorCheck): + (TParseContext::areAllChildConst): + (PaParseStrings): + * src/compiler/ParseHelper.h: + (TParseContext::TParseContext): + * src/compiler/PoolAlloc.cpp: + (InitializeGlobalPools): + (FreeGlobalPools): + (SetGlobalPoolAllocator): + (TPoolAllocator::TPoolAllocator): + (TPoolAllocator::~TPoolAllocator): + (TAllocation::checkAllocList): + * src/compiler/PoolAlloc.h: + * src/compiler/SearchSymbol.cpp: Added. + (sh::SearchSymbol::SearchSymbol): + (sh::SearchSymbol::traverse): + (sh::SearchSymbol::visitSymbol): + (sh::SearchSymbol::foundMatch): + * src/compiler/SearchSymbol.h: Added. + * src/compiler/ShHandle.h: + (TCompiler::getAsCompiler): + (TCompiler::getInfoSink): + (TCompiler::getAttribs): + (TCompiler::getUniforms): + (TCompiler::getShaderType): + (TCompiler::getShaderSpec): + * src/compiler/ShaderLang.cpp: + (getVariableMaxLength): + (getVariableInfo): + (ShInitBuiltInResources): + (ShConstructCompiler): + (ShCompile): + (ShGetInfo): + (ShGetInfoLog): + (ShGetObjectCode): + (ShGetActiveAttrib): + (ShGetActiveUniform): + * src/compiler/SymbolTable.cpp: + (TSymbolTableLevel::relateToExtension): + * src/compiler/SymbolTable.h: + (TVariable::shareConstPointer): + (TFunction::relateToExtension): + (TFunction::getExtension): + (TFunction::getParamCount): + (TFunction::getParam): + (TSymbolTable::getGlobalLevel): + (TSymbolTable::relateToOperator): + (TSymbolTable::relateToExtension): + * src/compiler/TranslatorGLSL.cpp: + (writeVersion): + (TranslatorGLSL::TranslatorGLSL): + (TranslatorGLSL::translate): + * src/compiler/TranslatorGLSL.h: + * src/compiler/TranslatorHLSL.cpp: + (TranslatorHLSL::TranslatorHLSL): + (TranslatorHLSL::translate): + * src/compiler/TranslatorHLSL.h: + * src/compiler/Types.h: + (TType::TType): + * src/compiler/UnfoldSelect.cpp: + (sh::UnfoldSelect::visitSelection): + * src/compiler/UnfoldSelect.h: + * src/compiler/ValidateLimitations.cpp: Added. + (ValidateLimitations::ValidateLimitations): + (ValidateLimitations::visitSymbol): + (ValidateLimitations::visitConstantUnion): + (ValidateLimitations::visitBinary): + (ValidateLimitations::visitUnary): + (ValidateLimitations::visitSelection): + (ValidateLimitations::visitAggregate): + (ValidateLimitations::visitLoop): + (ValidateLimitations::visitBranch): + (ValidateLimitations::error): + (ValidateLimitations::withinLoopBody): + (ValidateLimitations::isLoopIndex): + (ValidateLimitations::validateLoopType): + (ValidateLimitations::validateForLoopHeader): + (ValidateLimitations::validateForLoopInit): + (ValidateLimitations::validateForLoopCond): + (ValidateLimitations::validateForLoopExpr): + (ValidateLimitations::validateFunctionCall): + (ValidateLimitations::validateOperation): + (ValidateLimitations::isConstExpr): + (ValidateLimitations::isConstIndexExpr): + (ValidateLimitations::validateIndexing): + * src/compiler/ValidateLimitations.h: Added. + (ValidateLimitations::numErrors): + * src/compiler/VariableInfo.cpp: Added. + (arrayBrackets): + (getVariableDataType): + (getVariableInfo): + (getBuiltInVariableInfo): + (getUserDefinedVariableInfo): + (CollectAttribsUniforms::CollectAttribsUniforms): + (CollectAttribsUniforms::visitSymbol): + (CollectAttribsUniforms::visitConstantUnion): + (CollectAttribsUniforms::visitBinary): + (CollectAttribsUniforms::visitUnary): + (CollectAttribsUniforms::visitSelection): + (CollectAttribsUniforms::visitAggregate): + (CollectAttribsUniforms::visitLoop): + (CollectAttribsUniforms::visitBranch): + * src/compiler/VariableInfo.h: Added. + * src/compiler/VersionGLSL.cpp: Added. + (TVersionGLSL::TVersionGLSL): + (TVersionGLSL::visitSymbol): + (TVersionGLSL::visitConstantUnion): + (TVersionGLSL::visitBinary): + (TVersionGLSL::visitUnary): + (TVersionGLSL::visitSelection): + (TVersionGLSL::visitAggregate): + (TVersionGLSL::visitLoop): + (TVersionGLSL::visitBranch): + (TVersionGLSL::updateVersion): + * src/compiler/VersionGLSL.h: Added. + (TVersionGLSL::getVersion): + * src/compiler/generate_glslang_lexer.sh: Added. + * src/compiler/generate_glslang_parser.sh: Added. + * src/compiler/glslang.h: Added. + * src/compiler/glslang.l: + * src/compiler/glslang.y: + * src/compiler/glslang_lex.cpp: Added. + (yy_get_next_buffer): + (yy_get_previous_state): + (yy_try_NUL_trans): + (input): + (yyrestart): + (yy_switch_to_buffer): + (yy_load_buffer_state): + (yy_create_buffer): + (yy_delete_buffer): + (yy_init_buffer): + (yy_flush_buffer): + (yypush_buffer_state): + (yypop_buffer_state): + (yyensure_buffer_stack): + (yy_scan_buffer): + (yy_scan_string): + (yy_scan_bytes): + (yy_push_state): + (yy_pop_state): + (yy_top_state): + (yy_fatal_error): + (yyget_extra): + (yyget_lineno): + (yyget_column): + (yyget_in): + (yyget_out): + (yyget_leng): + (yyget_text): + (yyset_extra): + (yyset_lineno): + (yyset_column): + (yyset_in): + (yyset_out): + (yyget_debug): + (yyset_debug): + (yyget_lval): + (yyset_lval): + (yylex_init): + (yylex_init_extra): + (yy_init_globals): + (yylex_destroy): + (yy_flex_strncpy): + (yy_flex_strlen): + (yyalloc): + (yyrealloc): + (yyfree): + (string_input): + (check_type): + (reserved_word): + (yyerror): + (glslang_initialize): + (glslang_finalize): + (glslang_scan): + * src/compiler/glslang_tab.cpp: Added. + (yytnamerr): + (yysyntax_error): + (glslang_parse): + * src/compiler/glslang_tab.h: Added. + * src/compiler/intermOut.cpp: + (TOutputTraverser::TOutputTraverser): + (OutputTreeText): + (TOutputTraverser::visitSymbol): + (TOutputTraverser::visitBinary): + (TOutputTraverser::visitUnary): + (TOutputTraverser::visitAggregate): + (TOutputTraverser::visitSelection): + (TOutputTraverser::visitConstantUnion): + (TOutputTraverser::visitLoop): + (TOutputTraverser::visitBranch): + (TIntermediate::outputTree): + * src/compiler/intermediate.h: + (TIntermLoop::TIntermLoop): + (TIntermLoop::getType): + (TIntermLoop::getInit): + (TIntermLoop::getCondition): + (TIntermLoop::getExpression): + (TIntermLoop::getBody): + * src/compiler/localintermediate.h: + * src/compiler/osinclude.h: + (OS_GetTLSValue): + * src/compiler/ossource_nspr.cpp: Added. + (OS_AllocTLSIndex): + (OS_SetTLSValue): + (OS_FreeTLSIndex): + * src/compiler/preprocessor/compile.h: + * src/compiler/preprocessor/cpp.c: + (CPPdefine): + (CPPelse): + (CPPif): + (CPPifdef): + (CPPerror): + (CPPextension): + (readCPPline): + * src/compiler/preprocessor/preprocess.h: + * src/compiler/preprocessor/scanner.c: + (str_getch): + (str_ungetch): + (ScanFromString): + (lFloatConst): + (byte_scan): + (yylex_CPP): + (check_EOF): + * src/compiler/preprocessor/scanner.h: + * src/compiler/preprocessor/tokens.c: + (RecordToken): + (ReadToken): + * src/compiler/tools: Removed. + * src/compiler/unistd.h: Removed. + * src/compiler/util.cpp: Added. + (atof_dot): + * src/compiler/util.h: Added. + * src/libEGL/Config.cpp: + (egl::Config::set): + * src/libEGL/Display.cpp: + (egl::Display::Display): + (egl::Display::initialize): + (egl::Display::terminate): + (egl::Display::createDevice): + (egl::Display::resetDevice): + (egl::Display::createContext): + (egl::Display::destroyContext): + (egl::Display::getMinSwapInterval): + (egl::Display::getMaxSwapInterval): + (egl::Display::getDevice): + (egl::Display::getFloatTextureSupport): + (egl::Display::getHalfFloatTextureSupport): + (egl::Display::getLuminanceTextureSupport): + (egl::Display::getLuminanceAlphaTextureSupport): + (egl::Display::getBufferPool): + (egl::Display::getEventQuerySupport): + (egl::Display::getDefaultPresentParameters): + * src/libEGL/Display.h: + * src/libEGL/Surface.cpp: + (egl::Surface::Surface): + (egl::Surface::~Surface): + (egl::Surface::release): + (egl::Surface::resetSwapChain): + (egl::Surface::writeRecordableFlipState): + (egl::Surface::restoreState): + (egl::SurfaceWindowProc): + (egl::Surface::subclassWindow): + (egl::Surface::unsubclassWindow): + (egl::Surface::checkForOutOfDateSwapChain): + (egl::Surface::convertInterval): + (egl::Surface::swap): + (egl::Surface::getRenderTarget): + (egl::Surface::setSwapInterval): + * src/libEGL/Surface.h: + * src/libEGL/libEGL.cpp: + * src/libGLESv2/Blit.cpp: + (gl::Blit::copySurfaceToTexture): + (gl::Blit::setCommonBlitState): + * src/libGLESv2/Buffer.cpp: + (gl::Buffer::Buffer): + (gl::Buffer::~Buffer): + (gl::Buffer::bufferData): + (gl::Buffer::bufferSubData): + (gl::Buffer::getVertexBuffer): + (gl::Buffer::getIndexBuffer): + (gl::Buffer::invalidateStaticData): + * src/libGLESv2/Buffer.h: + * src/libGLESv2/Context.cpp: + (gl::Context::Context): + (gl::Context::~Context): + (gl::Context::makeCurrent): + (gl::Context::markAllStateDirty): + (gl::Context::setFragmentShaderDerivativeHint): + (gl::Context::setEnableVertexAttribArray): + (gl::Context::getVertexAttribState): + (gl::Context::getVertexAttributes): + (gl::Context::createFence): + (gl::Context::deleteFence): + (gl::Context::bindTexture2D): + (gl::Context::bindTextureCubeMap): + (gl::Context::getFence): + (gl::Context::getTexture2D): + (gl::Context::getTextureCubeMap): + (gl::Context::getSamplerTexture): + (gl::Context::getBooleanv): + (gl::Context::getIntegerv): + (gl::Context::getQueryParameterInfo): + (gl::Context::applyRenderTarget): + (gl::Context::applyState): + (gl::Context::lookupAttributeMapping): + (gl::Context::applyVertexBuffer): + (gl::Context::applyIndexBuffer): + (gl::Context::readPixels): + (gl::Context::clear): + (gl::Context::drawArrays): + (gl::Context::drawElements): + (gl::Context::finish): + (gl::Context::drawClosingLine): + (gl::Context::getMaximumVaryingVectors): + (gl::Context::getMaximumFragmentUniformVectors): + (gl::Context::supportsEventQueries): + (gl::Context::supportsFloatTextures): + (gl::Context::supportsFloatLinearFilter): + (gl::Context::supportsFloatRenderableTextures): + (gl::Context::supportsHalfFloatTextures): + (gl::Context::supportsHalfFloatLinearFilter): + (gl::Context::supportsHalfFloatRenderableTextures): + (gl::Context::getMaximumRenderbufferDimension): + (gl::Context::getMaximumTextureDimension): + (gl::Context::getMaximumCubeTextureDimension): + (gl::Context::getMaximumTextureLevel): + (gl::Context::supportsLuminanceTextures): + (gl::Context::supportsLuminanceAlphaTextures): + (gl::Context::supports32bitIndices): + (gl::Context::getIncompleteTexture): + (gl::Context::setVertexAttrib): + (gl::Context::initExtensionString): + (gl::Context::blitFramebuffer): + * src/libGLESv2/Context.h: + (gl::VertexAttribute::VertexAttribute): + (gl::VertexAttribute::typeSize): + (gl::VertexAttribute::stride): + * src/libGLESv2/Fence.cpp: Added. + (gl::Fence::Fence): + (gl::Fence::~Fence): + (gl::Fence::isFence): + (gl::Fence::setFence): + (gl::Fence::testFence): + (gl::Fence::finishFence): + (gl::Fence::getFenceiv): + * src/libGLESv2/Fence.h: Added. + * src/libGLESv2/Framebuffer.cpp: + (gl::Framebuffer::completeness): + (gl::DefaultFramebuffer::DefaultFramebuffer): + (gl::DefaultFramebuffer::completeness): + * src/libGLESv2/Program.cpp: + (gl::Program::Program): + (gl::Program::getSamplerMapping): + (gl::Program::getUniformLocation): + (gl::Program::setUniform1iv): + (gl::Program::applyUniforms): + (gl::Program::packVaryings): + (gl::Program::linkVaryings): + (gl::Program::link): + (gl::Program::defineUniform): + (gl::Program::createUniform): + (gl::Program::applyUniform1iv): + (gl::Program::resetInfoLog): + (gl::Program::unlink): + (gl::Program::getActiveAttribute): + (gl::Program::getActiveUniform): + (gl::Program::getDxDepthRangeLocation): + * src/libGLESv2/Program.h: + * src/libGLESv2/RefCountObject.cpp: + (gl::RefCountObject::~RefCountObject): + * src/libGLESv2/Renderbuffer.cpp: + (gl::RenderbufferStorage::RenderbufferStorage): + (gl::RenderbufferStorage::isFloatingPoint): + (gl::Colorbuffer::Colorbuffer): + (gl::DepthStencilbuffer::DepthStencilbuffer): + * src/libGLESv2/Renderbuffer.h: + * src/libGLESv2/Shader.cpp: + (gl::Shader::Shader): + (gl::Shader::parseVaryings): + (gl::Shader::compileToHLSL): + (gl::VertexShader::parseAttributes): + * src/libGLESv2/Texture.cpp: + (gl::Texture::Texture): + (gl::Texture::isFloatingPoint): + (gl::Texture::isRenderableFormat): + (gl::Texture::selectFormat): + (gl::Texture::loadImageData): + (gl::Texture::loadAlphaFloatImageData): + (gl::Texture::loadAlphaHalfFloatImageData): + (gl::Texture::loadLuminanceImageData): + (gl::Texture::loadLuminanceFloatImageData): + (gl::Texture::loadLuminanceHalfFloatImageData): + (gl::Texture::loadLuminanceAlphaImageData): + (gl::Texture::loadLuminanceAlphaFloatImageData): + (gl::Texture::loadLuminanceAlphaHalfFloatImageData): + (gl::Texture::loadRGBFloatImageData): + (gl::Texture::loadRGBHalfFloatImageData): + (gl::Texture::loadRGBAFloatImageData): + (gl::Texture::loadRGBAHalfFloatImageData): + (gl::Texture::createSurface): + (gl::Texture::setImage): + (gl::Texture::setCompressedImage): + (gl::Texture::subImage): + (gl::Texture::subImageCompressed): + (gl::Texture::copyNonRenderable): + (gl::Texture::getD3DFormat): + (gl::Texture::isRenderable): + (gl::Texture2D::Texture2D): + (gl::Texture2D::~Texture2D): + (gl::Texture2D::redefineTexture): + (gl::Texture2D::setImage): + (gl::Texture2D::setCompressedImage): + (gl::Texture2D::copyImage): + (gl::Texture2D::copySubImage): + (gl::Texture2D::isComplete): + (gl::Texture2D::createTexture): + (gl::Texture2D::convertToRenderTarget): + (gl::Texture2D::generateMipmaps): + (gl::Texture2D::getColorbuffer): + (gl::Texture2D::getRenderTarget): + (gl::TextureCubeMap::TextureCubeMap): + (gl::TextureCubeMap::~TextureCubeMap): + (gl::TextureCubeMap::subImage): + (gl::TextureCubeMap::subImageCompressed): + (gl::TextureCubeMap::isComplete): + (gl::TextureCubeMap::createTexture): + (gl::TextureCubeMap::convertToRenderTarget): + (gl::TextureCubeMap::redefineTexture): + (gl::TextureCubeMap::copyImage): + (gl::TextureCubeMap::copySubImage): + (gl::TextureCubeMap::generateMipmaps): + (gl::TextureCubeMap::getColorbuffer): + (gl::TextureCubeMap::getRenderTarget): + (gl::Texture::TextureColorbufferProxy::TextureColorbufferProxy): + (gl::Texture::TextureColorbufferProxy::isFloatingPoint): + * src/libGLESv2/Texture.h: + * src/libGLESv2/geometry/IndexDataManager.cpp: + (gl::IndexDataManager::IndexDataManager): + (gl::IndexDataManager::~IndexDataManager): + (gl::convertIndices): + (gl::computeRange): + (gl::IndexDataManager::prepareIndexData): + (gl::IndexDataManager::indexSize): + (gl::IndexDataManager::typeSize): + (gl::IndexBuffer::IndexBuffer): + (gl::IndexBuffer::~IndexBuffer): + (gl::IndexBuffer::getBuffer): + (gl::IndexBuffer::unmap): + (gl::StreamingIndexBuffer::StreamingIndexBuffer): + (gl::StreamingIndexBuffer::~StreamingIndexBuffer): + (gl::StreamingIndexBuffer::map): + (gl::StreamingIndexBuffer::reserveSpace): + (gl::StaticIndexBuffer::StaticIndexBuffer): + (gl::StaticIndexBuffer::~StaticIndexBuffer): + (gl::StaticIndexBuffer::map): + (gl::StaticIndexBuffer::reserveSpace): + (gl::StaticIndexBuffer::lookupType): + (gl::StaticIndexBuffer::lookupRange): + (gl::StaticIndexBuffer::addRange): + * src/libGLESv2/geometry/IndexDataManager.h: + (gl::IndexBuffer::size): + * src/libGLESv2/geometry/VertexDataManager.cpp: + (gl::VertexDataManager::VertexDataManager): + (gl::VertexDataManager::~VertexDataManager): + (gl::VertexDataManager::writeAttributeData): + (gl::VertexDataManager::prepareVertexData): + (gl::VertexDataManager::spaceRequired): + (gl::VertexDataManager::checkVertexCaps): + (gl::VertexDataManager::typeIndex): + (gl::VertexDataManager::setupAttributes): + (gl::VertexBuffer::VertexBuffer): + (gl::VertexBuffer::~VertexBuffer): + (gl::VertexBuffer::unmap): + (gl::VertexBuffer::getBuffer): + (gl::ConstantVertexBuffer::ConstantVertexBuffer): + (gl::ConstantVertexBuffer::~ConstantVertexBuffer): + (gl::ArrayVertexBuffer::ArrayVertexBuffer): + (gl::ArrayVertexBuffer::~ArrayVertexBuffer): + (gl::ArrayVertexBuffer::addRequiredSpace): + (gl::ArrayVertexBuffer::addRequiredSpaceFor): + (gl::StreamingVertexBuffer::StreamingVertexBuffer): + (gl::StreamingVertexBuffer::~StreamingVertexBuffer): + (gl::StreamingVertexBuffer::map): + (gl::StreamingVertexBuffer::reserveRequiredSpace): + (gl::StaticVertexBuffer::StaticVertexBuffer): + (gl::StaticVertexBuffer::~StaticVertexBuffer): + (gl::StaticVertexBuffer::map): + (gl::StaticVertexBuffer::reserveRequiredSpace): + (gl::StaticVertexBuffer::lookupAttribute): + (gl::VertexDataManager::formatConverter): + * src/libGLESv2/geometry/VertexDataManager.h: + (gl::ArrayVertexBuffer::size): + (gl::VertexDataManager::dirtyCurrentValue): + * src/libGLESv2/geometry/backend.cpp: Removed. + * src/libGLESv2/geometry/backend.h: Removed. + * src/libGLESv2/geometry/dx9.cpp: Removed. + * src/libGLESv2/geometry/dx9.h: Removed. + * src/libGLESv2/libGLESv2.cpp: + * src/libGLESv2/libGLESv2.def: + * src/libGLESv2/libGLESv2.vcproj: + * src/libGLESv2/utilities.cpp: + (gl::UniformComponentCount): + (gl::UniformComponentType): + (gl::ComputePixelSize): + (gl::CheckTextureFormatType): + (gl::IsColorRenderable): + (gl::IsDepthRenderable): + (gl::IsStencilRenderable): + (es2dx::GetAlphaSize): + (es2dx::GetRedSize): + (es2dx::GetGreenSize): + (es2dx::GetBlueSize): + (es2dx::GetDepthSize): + (es2dx::ConvertPrimitiveType): + (dx2es::ConvertBackBufferFormat): + (dx2es::ConvertDepthStencilFormat): + * src/libGLESv2/utilities.h: + +2011-01-17 Dan Bernstein <mitz@apple.com> + + Rubber-stamped by Mark Rowe. + + Update xcodeproj svn:ignore to include xcuserdata. + + * ANGLE.xcodeproj: Modified property svn:ignore. + * src/build_angle.xcodeproj: Modified property svn:ignore. + +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 000000000..644b71dda --- /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 000000000..4a84fb355 --- /dev/null +++ b/Source/ThirdParty/ANGLE/Configurations/Base.xcconfig @@ -0,0 +1,47 @@ +#include "CompilerVersion.xcconfig" + +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 = YES; +GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; +GCC_WARN_ABOUT_MISSING_NEWLINE = YES; +LINKER_DISPLAYS_MANGLED_NAMES = YES; +PREBINDING = NO; +STRIP_INSTALLED_PRODUCT = NO; + + +REAL_PLATFORM_NAME = $(REAL_PLATFORM_NAME_$(PLATFORM_NAME)); +REAL_PLATFORM_NAME_ = $(REAL_PLATFORM_NAME_macosx); +REAL_PLATFORM_NAME_iphoneos = iphoneos; +REAL_PLATFORM_NAME_iphonesimulator = iphonesimulator; +REAL_PLATFORM_NAME_macosx = macosx; + +TARGET_MAC_OS_X_VERSION_MAJOR = $(MAC_OS_X_VERSION_MAJOR); + +// 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_1060_1050 = macosx10.5; +SDKROOT_1070_1050 = macosx10.5; +SDKROOT_1080_1050 = macosx10.5; +SDKROOT_1090_1050 = macosx10.5; +SDKROOT_1070_1060 = macosx10.6; +SDKROOT_1080_1060 = macosx10.6; +SDKROOT_1090_1060 = macosx10.6; +SDKROOT_1080_1070 = macosx10.7; +SDKROOT_1090_1070 = macosx10.7; +SDKROOT_1090_1080 = macosx10.8; diff --git a/Source/ThirdParty/ANGLE/Configurations/CompilerVersion.xcconfig b/Source/ThirdParty/ANGLE/Configurations/CompilerVersion.xcconfig new file mode 100644 index 000000000..a8c7f75a0 --- /dev/null +++ b/Source/ThirdParty/ANGLE/Configurations/CompilerVersion.xcconfig @@ -0,0 +1,84 @@ +// Copyright (C) 2009, 2010, 2011 Apple Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +IS_XCODE_0400 = $(IS_XCODE_0400_$(XCODE_VERSION_MINOR)); +IS_XCODE_0400_0400 = YES; + +IS_XCODE_0400_OR_0410 = $(IS_XCODE_0400_OR_0410_$(XCODE_VERSION_MINOR)); +IS_XCODE_0400_OR_0410_0400 = YES; +IS_XCODE_0400_OR_0410_0410 = YES; + +// The version of the LLVM Compiler in Xcode 4.0 and earlier have difficulty compiling our code. +LLVM_COMPILER_UNSUITABLE_FOR_DEBUG_BUILDS = $(LLVM_COMPILER_UNSUITABLE_FOR_DEBUG_BUILDS_$(XCODE_VERSION_MAJOR)); +LLVM_COMPILER_UNSUITABLE_FOR_DEBUG_BUILDS_0300 = YES; +LLVM_COMPILER_UNSUITABLE_FOR_DEBUG_BUILDS_0400 = $(LLVM_COMPILER_UNSUITABLE_FOR_DEBUG_BUILDS_IS_XCODE_0400_$(IS_XCODE_0400)); +LLVM_COMPILER_UNSUITABLE_FOR_DEBUG_BUILDS_IS_XCODE_0400_YES = YES; + +// The version of the LLVM Compiler in Xcode 4.1 and earlier do not generate fast enough code. +LLVM_COMPILER_UNSUITABLE_FOR_OPTIMIZED_BUILDS = $(LLVM_COMPILER_UNSUITABLE_FOR_OPTIMIZED_BUILDS_$(XCODE_VERSION_MAJOR)); +LLVM_COMPILER_UNSUITABLE_FOR_OPTIMIZED_BUILDS_0300 = YES; +LLVM_COMPILER_UNSUITABLE_FOR_OPTIMIZED_BUILDS_0400 = $(LLVM_COMPILER_UNSUITABLE_FOR_OPTIMIZED_BUILDS_IS_XCODE_0400_OR_0410_$(IS_XCODE_0400_OR_0410)); +LLVM_COMPILER_UNSUITABLE_FOR_OPTIMIZED_BUILDS_IS_XCODE_0400_OR_0410_YES = YES; + +LLVM_COMPILER_SUITABLE_FOR_DEBUG_BUILDS = $(LLVM_COMPILER_SUITABLE_FOR_DEBUG_BUILDS_$(LLVM_COMPILER_UNSUITABLE_FOR_DEBUG_BUILDS)); +LLVM_COMPILER_SUITABLE_FOR_DEBUG_BUILDS_ = YES; +LLVM_COMPILER_SUITABLE_FOR_DEBUG_BUILDS_YES = NO; + +LLVM_COMPILER_SUITABLE_FOR_OPTIMIZED_BUILDS = $(LLVM_COMPILER_SUITABLE_FOR_OPTIMIZED_BUILDS_$(LLVM_COMPILER_UNSUITABLE_FOR_OPTIMIZED_BUILDS)); +LLVM_COMPILER_SUITABLE_FOR_OPTIMIZED_BUILDS_ = YES; +LLVM_COMPILER_SUITABLE_FOR_OPTIMIZED_BUILDS_YES = NO; + + +// 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_$(REAL_PLATFORM_NAME)); +TARGET_GCC_VERSION_iphoneos = LLVM_GCC_42; +TARGET_GCC_VERSION_iphonesimulator = GCC_42; +TARGET_GCC_VERSION_macosx = $(TARGET_GCC_VERSION_macosx_$(TARGET_MAC_OS_X_VERSION_MAJOR)); + +TARGET_GCC_VERSION_macosx_1050 = $(TARGET_GCC_VERSION_macosx_1050_$(XCODE_VERSION_MINOR)); +TARGET_GCC_VERSION_macosx_1050_ = $(TARGET_GCC_VERSION_macosx_1050_$(XCODE_VERSION_ACTUAL)); +TARGET_GCC_VERSION_macosx_1050_0310 = GCC_42; +TARGET_GCC_VERSION_macosx_1050_0320 = GCC_42; + +TARGET_GCC_VERSION_macosx_1060 = $(TARGET_GCC_VERSION_macosx_1060_AND_1070_$(CONFIGURATION)); +TARGET_GCC_VERSION_macosx_1070 = $(TARGET_GCC_VERSION_macosx_1060_AND_1070_$(CONFIGURATION)); +TARGET_GCC_VERSION_macosx_1060_AND_1070_Debug = $(TARGET_GCC_VERSION_macosx_USE_LLVM_COMPILER_$(LLVM_COMPILER_SUITABLE_FOR_DEBUG_BUILDS)); +TARGET_GCC_VERSION_macosx_1060_AND_1070_Release = $(TARGET_GCC_VERSION_macosx_USE_LLVM_COMPILER_$(LLVM_COMPILER_SUITABLE_FOR_OPTIMIZED_BUILDS)); +TARGET_GCC_VERSION_macosx_1060_AND_1070_Production = $(TARGET_GCC_VERSION_macosx_USE_LLVM_COMPILER_$(LLVM_COMPILER_SUITABLE_FOR_OPTIMIZED_BUILDS)); +TARGET_GCC_VERSION_macosx_1060_NON_LLVM_FALLBACK = GCC_42; +TARGET_GCC_VERSION_macosx_1070_NON_LLVM_FALLBACK = LLVM_GCC_42; + +TARGET_GCC_VERSION_macosx_USE_LLVM_COMPILER_YES = LLVM_COMPILER; +TARGET_GCC_VERSION_macosx_USE_LLVM_COMPILER_NO = $(TARGET_GCC_VERSION_macosx_$(TARGET_MAC_OS_X_VERSION_MAJOR)_NON_LLVM_FALLBACK); + +TARGET_GCC_VERSION_macosx_1080 = LLVM_COMPILER; +TARGET_GCC_VERSION_macosx_1090 = LLVM_COMPILER; + +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; +GCC_VERSION_LLVM_COMPILER = com.apple.compilers.llvm.clang.1_0; diff --git a/Source/ThirdParty/ANGLE/Configurations/DebugRelease.xcconfig b/Source/ThirdParty/ANGLE/Configurations/DebugRelease.xcconfig new file mode 100644 index 000000000..0236d3517 --- /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_1050 = $(NATIVE_ARCH); +ARCHS_1060 = $(ARCHS_STANDARD_32_64_BIT); +ARCHS_1070 = $(ARCHS_STANDARD_32_64_BIT); +ARCHS_1080 = $(ARCHS_STANDARD_32_64_BIT); +ARCHS_1090 = $(ARCHS_STANDARD_32_64_BIT); + +ONLY_ACTIVE_ARCH = YES; + +MACOSX_DEPLOYMENT_TARGET = $(MACOSX_DEPLOYMENT_TARGET_$(TARGET_MAC_OS_X_VERSION_MAJOR)); +MACOSX_DEPLOYMENT_TARGET_1050 = 10.5; +MACOSX_DEPLOYMENT_TARGET_1060 = 10.6; +MACOSX_DEPLOYMENT_TARGET_1070 = 10.7; +MACOSX_DEPLOYMENT_TARGET_1080 = 10.8; +MACOSX_DEPLOYMENT_TARGET_1090 = 10.9; + +GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; diff --git a/Source/ThirdParty/ANGLE/Makefile b/Source/ThirdParty/ANGLE/Makefile new file mode 100644 index 000000000..cb4c11a57 --- /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 000000000..99ea342a4 --- /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 000000000..b650a500c --- /dev/null +++ b/Source/ThirdParty/ANGLE/include/EGL/eglext.h @@ -0,0 +1,235 @@ +#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 + +#ifndef EGL_ANGLE_query_surface_pointer +#define EGL_ANGLE_query_surface_pointer 1 +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); +#endif +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); +#endif + +#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle +#define EGL_ANGLE_surface_d3d_texture_2d_share_handle +#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200 +#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 000000000..22e855f56 --- /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 000000000..e1d3b87cc --- /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 000000000..01844de4b --- /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 000000000..c9fa3c4d6 --- /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 000000000..6fe688c75 --- /dev/null +++ b/Source/ThirdParty/ANGLE/include/GLSLANG/ShaderLang.h @@ -0,0 +1,284 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +#ifndef _COMPILER_INTERFACE_INCLUDED_ +#define _COMPILER_INTERFACE_INCLUDED_ + +// +// This is the platform independent interface between an OGL driver +// and the shading language compiler. +// + +#ifdef __cplusplus +extern "C" { +#endif + +// Version number for shader translation API. +// It is incremented everytime the API changes. +#define SH_VERSION 105 + +// +// The names of the following enums have been derived by replacing GL prefix +// with SH. For example, SH_INFO_LOG_LENGTH is equivalent to GL_INFO_LOG_LENGTH. +// The enum values are also equal to the values of their GL counterpart. This +// is done to make it easier for applications to use the shader library. +// +typedef enum { + SH_FRAGMENT_SHADER = 0x8B30, + SH_VERTEX_SHADER = 0x8B31 +} ShShaderType; + +typedef enum { + SH_GLES2_SPEC = 0x8B40, + SH_WEBGL_SPEC = 0x8B41 +} ShShaderSpec; + +typedef enum { + SH_ESSL_OUTPUT = 0x8B45, + SH_GLSL_OUTPUT = 0x8B46, + SH_HLSL_OUTPUT = 0x8B47 +} ShShaderOutput; + +typedef enum { + SH_NONE = 0, + SH_INT = 0x1404, + SH_FLOAT = 0x1406, + SH_FLOAT_VEC2 = 0x8B50, + SH_FLOAT_VEC3 = 0x8B51, + SH_FLOAT_VEC4 = 0x8B52, + SH_INT_VEC2 = 0x8B53, + SH_INT_VEC3 = 0x8B54, + SH_INT_VEC4 = 0x8B55, + SH_BOOL = 0x8B56, + SH_BOOL_VEC2 = 0x8B57, + SH_BOOL_VEC3 = 0x8B58, + SH_BOOL_VEC4 = 0x8B59, + SH_FLOAT_MAT2 = 0x8B5A, + SH_FLOAT_MAT3 = 0x8B5B, + SH_FLOAT_MAT4 = 0x8B5C, + SH_SAMPLER_2D = 0x8B5E, + SH_SAMPLER_CUBE = 0x8B60 +} ShDataType; + +typedef enum { + SH_INFO_LOG_LENGTH = 0x8B84, + SH_OBJECT_CODE_LENGTH = 0x8B88, // GL_SHADER_SOURCE_LENGTH + SH_ACTIVE_UNIFORMS = 0x8B86, + SH_ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87, + SH_ACTIVE_ATTRIBUTES = 0x8B89, + SH_ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A, + SH_MAPPED_NAME_MAX_LENGTH = 0x8B8B +} ShShaderInfo; + +// Compile options. +typedef enum { + SH_VALIDATE = 0, + SH_VALIDATE_LOOP_INDEXING = 0x0001, + SH_INTERMEDIATE_TREE = 0x0002, + SH_OBJECT_CODE = 0x0004, + SH_ATTRIBUTES_UNIFORMS = 0x0008, + SH_LINE_DIRECTIVES = 0x0010, + SH_SOURCE_PATH = 0x0020, + SH_MAP_LONG_VARIABLE_NAMES = 0x0040 +} ShCompileOptions; + +// +// Driver must call this first, once, before doing any other +// compiler operations. +// If the function succeeds, the return value is nonzero, else zero. +// +int ShInitialize(); +// +// Driver should call this at shutdown. +// If the function succeeds, the return value is nonzero, else zero. +// +int ShFinalize(); + +// +// Implementation dependent built-in resources (constants and extensions). +// The names for these resources has been obtained by stripping gl_/GL_. +// +typedef struct +{ + // Constants. + int MaxVertexAttribs; + int MaxVertexUniformVectors; + int MaxVaryingVectors; + int MaxVertexTextureImageUnits; + int MaxCombinedTextureImageUnits; + int MaxTextureImageUnits; + int MaxFragmentUniformVectors; + int MaxDrawBuffers; + + // Extensions. + // Set to 1 to enable the extension, else 0. + int OES_standard_derivatives; +} ShBuiltInResources; + +// +// Initialize built-in resources with minimum expected values. +// +void ShInitBuiltInResources(ShBuiltInResources* resources); + +// +// ShHandle held by but opaque to the driver. It is allocated, +// managed, and de-allocated by the compiler. It's contents +// are defined by and used by the compiler. +// +// If handle creation fails, 0 will be returned. +// +typedef void* ShHandle; + +// +// Driver calls these to create and destroy compiler objects. +// +// Returns the handle of constructed compiler, null if the requested compiler is +// not supported. +// Parameters: +// type: Specifies the type of shader - SH_FRAGMENT_SHADER or SH_VERTEX_SHADER. +// spec: Specifies the language spec the compiler must conform to - +// SH_GLES2_SPEC or SH_WEBGL_SPEC. +// output: Specifies the output code type - SH_ESSL_OUTPUT, SH_GLSL_OUTPUT, +// or SH_HLSL_OUTPUT. +// resources: Specifies the built-in resources. +ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, + ShShaderOutput output, + const ShBuiltInResources* resources); +void ShDestruct(ShHandle handle); + +// +// Compiles the given shader source. +// If the function succeeds, the return value is nonzero, else zero. +// Parameters: +// handle: Specifies the handle of compiler to be used. +// shaderStrings: Specifies an array of pointers to null-terminated strings +// containing the shader source code. +// numStrings: Specifies the number of elements in shaderStrings array. +// compileOptions: A mask containing the following parameters: +// SH_VALIDATE: Validates shader to ensure that it conforms to the spec +// specified during compiler construction. +// SH_VALIDATE_LOOP_INDEXING: Validates loop and indexing in the shader to +// ensure that they do not exceed the minimum +// functionality mandated in GLSL 1.0 spec, +// Appendix A, Section 4 and 5. +// There is no need to specify this parameter when +// compiling for WebGL - it is implied. +// SH_INTERMEDIATE_TREE: Writes intermediate tree to info log. +// Can be queried by calling ShGetInfoLog(). +// SH_OBJECT_CODE: Translates intermediate tree to glsl or hlsl shader. +// Can be queried by calling ShGetObjectCode(). +// SH_ATTRIBUTES_UNIFORMS: Extracts attributes and uniforms. +// Can be queried by calling ShGetActiveAttrib() and +// ShGetActiveUniform(). +// +int ShCompile( + const ShHandle handle, + const char* const shaderStrings[], + const int numStrings, + int compileOptions + ); + +// Returns a parameter from a compiled shader. +// Parameters: +// handle: Specifies the compiler +// pname: Specifies the parameter to query. +// The following parameters are defined: +// SH_INFO_LOG_LENGTH: the number of characters in the information log +// including the null termination character. +// SH_OBJECT_CODE_LENGTH: the number of characters in the object code +// including the null termination character. +// SH_ACTIVE_ATTRIBUTES: the number of active attribute variables. +// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: the length of the longest active attribute +// variable name including the null +// termination character. +// SH_ACTIVE_UNIFORMS: the number of active uniform variables. +// SH_ACTIVE_UNIFORM_MAX_LENGTH: the length of the longest active uniform +// variable name including the null +// termination character. +// SH_MAPPED_NAME_MAX_LENGTH: the length of the mapped variable name including +// the null termination character. +// +// params: Requested parameter +void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params); + +// Returns nul-terminated information log for a compiled shader. +// Parameters: +// handle: Specifies the compiler +// infoLog: Specifies an array of characters that is used to return +// the information log. It is assumed that infoLog has enough memory +// to accomodate the information log. The size of the buffer required +// to store the returned information log can be obtained by calling +// ShGetInfo with SH_INFO_LOG_LENGTH. +void ShGetInfoLog(const ShHandle handle, char* infoLog); + +// Returns null-terminated object code for a compiled shader. +// Parameters: +// handle: Specifies the compiler +// infoLog: Specifies an array of characters that is used to return +// the object code. It is assumed that infoLog has enough memory to +// accomodate the object code. The size of the buffer required to +// store the returned object code can be obtained by calling +// ShGetInfo with SH_OBJECT_CODE_LENGTH. +void ShGetObjectCode(const ShHandle handle, char* objCode); + +// Returns information about an active attribute variable. +// Parameters: +// handle: Specifies the compiler +// index: Specifies the index of the attribute variable to be queried. +// length: Returns the number of characters actually written in the string +// indicated by name (excluding the null terminator) if a value other +// than NULL is passed. +// size: Returns the size of the attribute variable. +// type: Returns the data type of the attribute variable. +// name: Returns a null terminated string containing the name of the +// attribute variable. It is assumed that name has enough memory to +// accomodate the attribute variable name. The size of the buffer +// required to store the attribute variable name can be obtained by +// calling ShGetInfo with SH_ACTIVE_ATTRIBUTE_MAX_LENGTH. +// mappedName: Returns a null terminated string containing the mapped name of +// the attribute variable, It is assumed that mappedName has enough +// memory (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care +// about the mapped name. If the name is not mapped, then name and +// mappedName are the same. +void ShGetActiveAttrib(const ShHandle handle, + int index, + int* length, + int* size, + ShDataType* type, + char* name, + char* mappedName); + +// Returns information about an active uniform variable. +// Parameters: +// handle: Specifies the compiler +// index: Specifies the index of the uniform variable to be queried. +// length: Returns the number of characters actually written in the string +// indicated by name (excluding the null terminator) if a value +// other than NULL is passed. +// size: Returns the size of the uniform variable. +// type: Returns the data type of the uniform variable. +// name: Returns a null terminated string containing the name of the +// uniform variable. It is assumed that name has enough memory to +// accomodate the uniform variable name. The size of the buffer required +// to store the uniform variable name can be obtained by calling +// ShGetInfo with SH_ACTIVE_UNIFORMS_MAX_LENGTH. +// mappedName: Returns a null terminated string containing the mapped name of +// the uniform variable, It is assumed that mappedName has enough +// memory (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care +// about the mapped name. If the name is not mapped, then name and +// mappedName are the same. +void ShGetActiveUniform(const ShHandle handle, + int index, + int* length, + int* size, + ShDataType* type, + char* name, + char* mappedName); + +#ifdef __cplusplus +} +#endif + +#endif // _COMPILER_INTERFACE_INCLUDED_ diff --git a/Source/ThirdParty/ANGLE/include/KHR/khrplatform.h b/Source/ThirdParty/ANGLE/include/KHR/khrplatform.h new file mode 100644 index 000000000..8ec0d199f --- /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 000000000..409b62278 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/build_angle.xcodeproj/project.pbxproj @@ -0,0 +1,687 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXAggregateTarget section */ + 1563D9916BFDAD853032CE1A /* All */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 77CEFB7B40F05B0A804E6B2B /* Build configuration list for PBXAggregateTarget "All" */; + buildPhases = ( + ); + dependencies = ( + A15E78BECDFF20BC3FFF040A /* PBXTargetDependency */, + BA246CA19435A9FA8AC69146 /* PBXTargetDependency */, + E4A3D33CA49D013550B8BA5F /* PBXTargetDependency */, + ); + name = All; + productName = All; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 05563ADFEA15116D7233332F /* QualifierAlive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4857E18799D332C30EF460C7 /* QualifierAlive.cpp */; }; + 08A7933BD2F78A86B90200F6 /* Compiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A118E5003E5C0E253C53839 /* Compiler.cpp */; }; + 0A216949103E1E228F9C12F0 /* InitializeDll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 60C3998C9CE66DE0C5B0FD99 /* InitializeDll.cpp */; }; + 0AC1897E461A0D4758E3DCE3 /* VersionGLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F727AEC906712EC238041464 /* VersionGLSL.cpp */; }; + 0E9456F464E16392D1CCD030 /* ValidateLimitations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B148D967B8D288A8267BFF3A /* ValidateLimitations.cpp */; }; + 0EC09B3B254829F8F1D952D3 /* ForLoopUnroll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5DC9B647E10F65F66142ECC1 /* ForLoopUnroll.cpp */; }; + 1ED1D2C7C74C6B625AFB1CCF /* VariableInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27C11EE10FED2979931FFC11 /* VariableInfo.cpp */; }; + 296466566D8C0F023A553760 /* SearchSymbol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 228A6DEDDF08DB370394A7AD /* SearchSymbol.cpp */; }; + 2E7C0D3804B8308A493D9B4B /* glslang_tab.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F68A6AA811495718A6938C0 /* glslang_tab.cpp */; }; + 3021E0BF1BC8442FF1F2F2B4 /* glslang_lex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 73A57C6D413773AEBA3C47A6 /* glslang_lex.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 */; }; + 3F18389BCB89370A930667F4 /* TranslatorGLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6FB70DC74A21FBCD665ABDF9 /* TranslatorGLSL.cpp */; }; + 40FC189B8A246EDF14C2FDE3 /* intermOut.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEAF6F3126C2EC4397785C3F /* intermOut.cpp */; }; + 4B4BDE7AD6266B39ED43C2D4 /* CodeGenHLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C49549DCCAF450EB761520E1 /* CodeGenHLSL.cpp */; }; + 50DF00005CC4212F6FB1291D /* Intermediate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F7C486C370A72938FE8160F /* Intermediate.cpp */; }; + 55CBD87573B803A173AC9129 /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3EE7215A7AB4EF71C97D2545 /* util.cpp */; }; + 5F7B52A54DCE8155ED94ECF8 /* OutputHLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A5B5BB2526802479E19F993 /* OutputHLSL.cpp */; }; + 6F9F875017A68ABE5D39FF19 /* ParseHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 976C831A75EBE009A9861796 /* ParseHelper.cpp */; }; + 888F1382498E2D74AF2801C8 /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4ABA230FEA3654B030E4C4FB /* debug.cpp */; }; + 896B720BD21F6749A7D83F30 /* MapLongVariableNames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57CF1F83E842901C42D44825 /* MapLongVariableNames.cpp */; }; + 93A41AF036E5EF87B366B563 /* TranslatorESSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A3A260F5379A7E2655D40F3 /* TranslatorESSL.cpp */; }; + 9886BCD5D0DD69B6FDE09DD8 /* UnfoldSelect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3711A48A0BF16B1CBD77AC9 /* UnfoldSelect.cpp */; }; + 9B111B83FB636FD5CDEC32A0 /* OutputGLSLBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCDF01F002ADE9DB8A3EF4FE /* OutputGLSLBase.cpp */; }; + 9E8DFE1CCEF038BF2B65428C /* parseConst.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D2C9C8EB4A7EFF5B67FF9DBF /* parseConst.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 */; }; + C4AAB2BB4594C0DA318DCB1C /* OutputESSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DB2917C5B624712364DE4A75 /* OutputESSL.cpp */; }; + C75EB9292A0DDA45592A8ACF /* OutputGLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 48B7402CC07A059FEF5EC351 /* OutputGLSL.cpp */; }; + CB7F0EF0D6A89FA8C4DF5513 /* cpp.c in Sources */ = {isa = PBXBuildFile; fileRef = B75707B393B7EAB7DD9999CB /* cpp.c */; }; + D56F7D00E9B162E416D37DF0 /* CodeGenGLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B7B1127C75B576FC00D74AED /* CodeGenGLSL.cpp */; }; + E1C7C5DFF0B2DFEC09387F4E /* PoolAlloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B64EABE738FC666A5E4E2F42 /* PoolAlloc.cpp */; }; + E8C727AA8E9DC5E7B58857DF /* tokens.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D00745DA9914FDE274D03D5 /* tokens.c */; }; + E99D6D80DBF05ECE7108B26D /* TranslatorHLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C3DAFF6BF12BB7F4784D6C7E /* TranslatorHLSL.cpp */; }; + 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 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 1F7242496103EDF29CC25D87 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DA188D8C6BF8073122539131 /* Project object */; + proxyType = 1; + remoteGlobalIDString = A838E9574B3FF14791DBDAB1; + remoteInfo = translator_hlsl; + }; + 55D5F9BF727E4A3B6637802B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DA188D8C6BF8073122539131 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6F4FD35CB3DFC89D70ECD432; + remoteInfo = translator_common; + }; + 60D3546AC27B094D6CA04CD6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DA188D8C6BF8073122539131 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5892C7A3695330437AFE5714; + remoteInfo = translator_glsl; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 056FEADC7D95C6D4C9CF1113 /* scanner.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = scanner.h; sourceTree = "<group>"; }; + 0A118E5003E5C0E253C53839 /* Compiler.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Compiler.cpp; sourceTree = "<group>"; }; + 0A3A260F5379A7E2655D40F3 /* TranslatorESSL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TranslatorESSL.cpp; sourceTree = "<group>"; }; + 0C9B4616A65A5ABEF91FD6DC /* atom.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = atom.c; sourceTree = "<group>"; }; + 120AD0A3B7642FB5A9AE3A56 /* VersionGLSL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VersionGLSL.h; 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>"; }; + 182BAD50D4E58B884F5EB9F3 /* ForLoopUnroll.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ForLoopUnroll.h; sourceTree = "<group>"; }; + 228A6DEDDF08DB370394A7AD /* SearchSymbol.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SearchSymbol.cpp; sourceTree = "<group>"; }; + 27C11EE10FED2979931FFC11 /* VariableInfo.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VariableInfo.cpp; 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; }; + 3EE7215A7AB4EF71C97D2545 /* util.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = util.cpp; sourceTree = "<group>"; }; + 3F68A6AA811495718A6938C0 /* glslang_tab.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = glslang_tab.cpp; sourceTree = "<group>"; }; + 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>"; }; + 497C5C24EEF466FB4B50A259 /* glslang.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = glslang.h; sourceTree = "<group>"; }; + 4ABA230FEA3654B030E4C4FB /* debug.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = debug.cpp; sourceTree = "<group>"; }; + 4FCF32CB2D8A42C930A66B00 /* glslang_tab.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = glslang_tab.h; 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>"; }; + 57CF1F83E842901C42D44825 /* MapLongVariableNames.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MapLongVariableNames.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>"; }; + 5D99354C4D8187D384C81207 /* VariableInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VariableInfo.h; sourceTree = "<group>"; }; + 5DC9B647E10F65F66142ECC1 /* ForLoopUnroll.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ForLoopUnroll.cpp; sourceTree = "<group>"; }; + 60C3998C9CE66DE0C5B0FD99 /* InitializeDll.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InitializeDll.cpp; sourceTree = "<group>"; }; + 6BB66AB5873868E23675B6DB /* OutputESSL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OutputESSL.h; 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>"; }; + 73A57C6D413773AEBA3C47A6 /* glslang_lex.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = glslang_lex.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>"; }; + 81CC4245A8E5AB5584D336F3 /* MapLongVariableNames.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MapLongVariableNames.h; 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>"; }; + 90254842D72975672C2E9A93 /* ValidateLimitations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ValidateLimitations.h; 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>"; }; + A1644B00E9304C407FDC5F47 /* libtranslator_glsl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libtranslator_glsl.a; sourceTree = BUILT_PRODUCTS_DIR; }; + A447F75F33DA4C4C123AC952 /* libtranslator_hlsl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libtranslator_hlsl.a; sourceTree = BUILT_PRODUCTS_DIR; }; + A51C728B615B41E1D59E9902 /* util.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = util.h; 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>"; }; + B148D967B8D288A8267BFF3A /* ValidateLimitations.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ValidateLimitations.cpp; 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>"; }; + B55B359CF7E486DBC49BBF0A /* OutputGLSLBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OutputGLSLBase.h; 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>"; }; + BCDF01F002ADE9DB8A3EF4FE /* OutputGLSLBase.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = OutputGLSLBase.cpp; 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>"; }; + 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>"; }; + D53DDD0CDF15EE1DD01F1A20 /* TranslatorESSL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TranslatorESSL.h; sourceTree = "<group>"; }; + DB2917C5B624712364DE4A75 /* OutputESSL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = OutputESSL.cpp; 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>"; }; + F3E09DC8E1BF5D2958AACEDE /* SearchSymbol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SearchSymbol.h; sourceTree = "<group>"; }; + F727AEC906712EC238041464 /* VersionGLSL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VersionGLSL.cpp; 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>"; }; + F99E737D3FFD30CA5E354150 /* common.gypi */ = {isa = PBXFileReference; lastKnownFileType = text; name = common.gypi; path = ../build/common.gypi; sourceTree = "<group>"; }; + 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; + }; + CA71CBA633EFC63166BEC9F3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FE3679A0955B25EB7BF116E6 /* 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 */, + 0A118E5003E5C0E253C53839 /* Compiler.cpp */, + B2F5CA11EEA92DF2384EFD93 /* ConstantUnion.h */, + 5DC9B647E10F65F66142ECC1 /* ForLoopUnroll.cpp */, + 182BAD50D4E58B884F5EB9F3 /* ForLoopUnroll.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 */, + 57CF1F83E842901C42D44825 /* MapLongVariableNames.cpp */, + 81CC4245A8E5AB5584D336F3 /* MapLongVariableNames.h */, + DB2917C5B624712364DE4A75 /* OutputESSL.cpp */, + 6BB66AB5873868E23675B6DB /* OutputESSL.h */, + 48B7402CC07A059FEF5EC351 /* OutputGLSL.cpp */, + 93D61CB0BCE54E069D71F920 /* OutputGLSL.h */, + BCDF01F002ADE9DB8A3EF4FE /* OutputGLSLBase.cpp */, + B55B359CF7E486DBC49BBF0A /* OutputGLSLBase.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 */, + 228A6DEDDF08DB370394A7AD /* SearchSymbol.cpp */, + F3E09DC8E1BF5D2958AACEDE /* SearchSymbol.h */, + AE65E139AE10DE9EFAD8D5B1 /* ShHandle.h */, + 56C7E99BA500A84C35216FE0 /* ShaderLang.cpp */, + B7E5B0F04635E6090F0DE8EF /* SymbolTable.cpp */, + 7C6BB12AB099556CF379D78F /* SymbolTable.h */, + 0A3A260F5379A7E2655D40F3 /* TranslatorESSL.cpp */, + D53DDD0CDF15EE1DD01F1A20 /* TranslatorESSL.h */, + 6FB70DC74A21FBCD665ABDF9 /* TranslatorGLSL.cpp */, + DDD3B7E3B7B35A0B8469AB87 /* TranslatorGLSL.h */, + C3DAFF6BF12BB7F4784D6C7E /* TranslatorHLSL.cpp */, + E3A29B6E9C21B67C25FF0D2B /* TranslatorHLSL.h */, + AA53B6632C76F905DF08E564 /* Types.h */, + E3711A48A0BF16B1CBD77AC9 /* UnfoldSelect.cpp */, + 2A765B86CBAF0D4A3E69DCA7 /* UnfoldSelect.h */, + B148D967B8D288A8267BFF3A /* ValidateLimitations.cpp */, + 90254842D72975672C2E9A93 /* ValidateLimitations.h */, + 27C11EE10FED2979931FFC11 /* VariableInfo.cpp */, + 5D99354C4D8187D384C81207 /* VariableInfo.h */, + F727AEC906712EC238041464 /* VersionGLSL.cpp */, + 120AD0A3B7642FB5A9AE3A56 /* VersionGLSL.h */, + 4ABA230FEA3654B030E4C4FB /* debug.cpp */, + 95276AA6B36FC1B1D913FCE4 /* debug.h */, + 497C5C24EEF466FB4B50A259 /* glslang.h */, + 73A57C6D413773AEBA3C47A6 /* glslang_lex.cpp */, + 3F68A6AA811495718A6938C0 /* glslang_tab.cpp */, + 4FCF32CB2D8A42C930A66B00 /* glslang_tab.h */, + DEAF6F3126C2EC4397785C3F /* intermOut.cpp */, + 799DC9611EE2EA3BA7CF5477 /* intermediate.h */, + 153BF06BF12C6F50496C6156 /* localintermediate.h */, + C8BD59BD7056FFC21373C50A /* osinclude.h */, + BE258486005F6696CC031622 /* ossource_posix.cpp */, + D2C9C8EB4A7EFF5B67FF9DBF /* parseConst.cpp */, + AE7674C52BDDDB28AF5FFD9F /* unistd.h */, + 3EE7215A7AB4EF71C97D2545 /* util.cpp */, + A51C728B615B41E1D59E9902 /* util.h */, + ); + name = Source; + path = compiler; + sourceTree = "<group>"; + }; + 5BBEFF9B91738297B95C568D = { + isa = PBXGroup; + children = ( + 196DB6AB006BB83503C7D786 /* Source */, + E0EDC4130E7D374318CE72BE /* Products */, + B2C184C3543198BA51592EA4 /* Build */, + ); + sourceTree = "<group>"; + }; + B2C184C3543198BA51592EA4 /* Build */ = { + isa = PBXGroup; + children = ( + CF2B62E0820C831AF812D000 /* build_angle.gyp */, + F99E737D3FFD30CA5E354150 /* common.gypi */, + ); + name = Build; + sourceTree = "<group>"; + }; + E0EDC4130E7D374318CE72BE /* Products */ = { + isa = PBXGroup; + children = ( + 3DDDC77216202A4DE1808BDB /* libtranslator_common.a */, + A1644B00E9304C407FDC5F47 /* libtranslator_glsl.a */, + A447F75F33DA4C4C123AC952 /* libtranslator_hlsl.a */, + ); + name = Products; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 5892C7A3695330437AFE5714 /* translator_glsl */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8B8815CA2EFE60FD0C0361BF /* Build configuration list for PBXNativeTarget "translator_glsl" */; + buildPhases = ( + BABCE721106B5C1527EFEF0D /* Sources */, + CA71CBA633EFC63166BEC9F3 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = translator_glsl; + productName = translator_glsl; + productReference = A1644B00E9304C407FDC5F47 /* libtranslator_glsl.a */; + productType = "com.apple.product-type.library.static"; + }; + 6F4FD35CB3DFC89D70ECD432 /* translator_common */ = { + isa = PBXNativeTarget; + buildConfigurationList = 34BB38E3A74418B2A063B49E /* Build configuration list for PBXNativeTarget "translator_common" */; + buildPhases = ( + EAA22CA63FD572FCCB913D22 /* Sources */, + A5C994E74DB1E60338E7BC11 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = translator_common; + productName = translator_common; + productReference = 3DDDC77216202A4DE1808BDB /* libtranslator_common.a */; + productType = "com.apple.product-type.library.static"; + }; + A838E9574B3FF14791DBDAB1 /* translator_hlsl */ = { + isa = PBXNativeTarget; + buildConfigurationList = C71E79C7829FD796CF621B44 /* Build configuration list for PBXNativeTarget "translator_hlsl" */; + buildPhases = ( + 05F3BCA9518770BE3F1E0A38 /* Sources */, + FE3679A0955B25EB7BF116E6 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = translator_hlsl; + productName = translator_hlsl; + productReference = A447F75F33DA4C4C123AC952 /* libtranslator_hlsl.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"; + hasScannedForEncodings = 1; + mainGroup = 5BBEFF9B91738297B95C568D; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1563D9916BFDAD853032CE1A /* All */, + 6F4FD35CB3DFC89D70ECD432 /* translator_common */, + 5892C7A3695330437AFE5714 /* translator_glsl */, + A838E9574B3FF14791DBDAB1 /* translator_hlsl */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 05F3BCA9518770BE3F1E0A38 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B4BDE7AD6266B39ED43C2D4 /* CodeGenHLSL.cpp in Sources */, + 5F7B52A54DCE8155ED94ECF8 /* OutputHLSL.cpp in Sources */, + E99D6D80DBF05ECE7108B26D /* TranslatorHLSL.cpp in Sources */, + 9886BCD5D0DD69B6FDE09DD8 /* UnfoldSelect.cpp in Sources */, + 296466566D8C0F023A553760 /* SearchSymbol.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BABCE721106B5C1527EFEF0D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D56F7D00E9B162E416D37DF0 /* CodeGenGLSL.cpp in Sources */, + 0EC09B3B254829F8F1D952D3 /* ForLoopUnroll.cpp in Sources */, + C4AAB2BB4594C0DA318DCB1C /* OutputESSL.cpp in Sources */, + 9B111B83FB636FD5CDEC32A0 /* OutputGLSLBase.cpp in Sources */, + C75EB9292A0DDA45592A8ACF /* OutputGLSL.cpp in Sources */, + 93A41AF036E5EF87B366B563 /* TranslatorESSL.cpp in Sources */, + 3F18389BCB89370A930667F4 /* TranslatorGLSL.cpp in Sources */, + 0AC1897E461A0D4758E3DCE3 /* VersionGLSL.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EAA22CA63FD572FCCB913D22 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 08A7933BD2F78A86B90200F6 /* Compiler.cpp in Sources */, + 888F1382498E2D74AF2801C8 /* debug.cpp in Sources */, + 3021E0BF1BC8442FF1F2F2B4 /* glslang_lex.cpp in Sources */, + 2E7C0D3804B8308A493D9B4B /* glslang_tab.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 */, + 896B720BD21F6749A7D83F30 /* MapLongVariableNames.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 */, + 55CBD87573B803A173AC9129 /* util.cpp in Sources */, + 0E9456F464E16392D1CCD030 /* ValidateLimitations.cpp in Sources */, + 1ED1D2C7C74C6B625AFB1CCF /* VariableInfo.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 */, + B4858417E54365BE8CDE3919 /* ossource_posix.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + A15E78BECDFF20BC3FFF040A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6F4FD35CB3DFC89D70ECD432 /* translator_common */; + targetProxy = 55D5F9BF727E4A3B6637802B /* PBXContainerItemProxy */; + }; + BA246CA19435A9FA8AC69146 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5892C7A3695330437AFE5714 /* translator_glsl */; + targetProxy = 60D3546AC27B094D6CA04CD6 /* PBXContainerItemProxy */; + }; + E4A3D33CA49D013550B8BA5F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = A838E9574B3FF14791DBDAB1 /* translator_hlsl */; + targetProxy = 1F7242496103EDF29CC25D87 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 322A8C62423B595E11BAD42D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = All; + }; + name = Debug; + }; + 4DA42A78D3B855C9CD8F658D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + EXECUTABLE_PREFIX = lib; + GCC_PREPROCESSOR_DEFINITIONS = ( + "\"ANGLE_DISABLE_TRACE\"", + "\"ANGLE_COMPILE_OPTIMIZATION_LEVEL=D3DCOMPILE_OPTIMIZATION_LEVEL0\"", + ); + HEADER_SEARCH_PATHS = ( + ., + ../include, + ); + PRODUCT_NAME = translator_common; + }; + name = Release; + }; + 4F851F5BA5FA43E9E0B9CB86 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = All; + }; + name = Release; + }; + 88ADC9285519A668808B51EE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + EXECUTABLE_PREFIX = lib; + GCC_PREPROCESSOR_DEFINITIONS = ( + "\"ANGLE_DISABLE_TRACE\"", + "\"ANGLE_COMPILE_OPTIMIZATION_LEVEL=D3DCOMPILE_OPTIMIZATION_LEVEL0\"", + ); + HEADER_SEARCH_PATHS = ( + ., + ../include, + ); + PRODUCT_NAME = translator_glsl; + }; + name = Debug; + }; + 9DC66E1FF9349CDCC8D52C46 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INTERMEDIATE_DIR = "$(PROJECT_DERIVED_FILE_DIR)/$(CONFIGURATION)"; + SHARED_INTERMEDIATE_DIR = "$(SYMROOT)/DerivedSources/$(CONFIGURATION)"; + }; + name = Debug; + }; + AF7C2CD10C6FEA076B141E6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + EXECUTABLE_PREFIX = lib; + GCC_PREPROCESSOR_DEFINITIONS = ( + "\"ANGLE_DISABLE_TRACE\"", + "\"ANGLE_COMPILE_OPTIMIZATION_LEVEL=D3DCOMPILE_OPTIMIZATION_LEVEL0\"", + ); + HEADER_SEARCH_PATHS = ( + ., + ../include, + ); + PRODUCT_NAME = translator_glsl; + }; + name = Release; + }; + B096FAF032DB19AB637D38F0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + EXECUTABLE_PREFIX = lib; + GCC_PREPROCESSOR_DEFINITIONS = ( + "\"ANGLE_DISABLE_TRACE\"", + "\"ANGLE_COMPILE_OPTIMIZATION_LEVEL=D3DCOMPILE_OPTIMIZATION_LEVEL0\"", + ); + HEADER_SEARCH_PATHS = ( + ., + ../include, + ); + PRODUCT_NAME = translator_hlsl; + }; + name = Release; + }; + C4546B14B0EB5EB8C5D39DC2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INTERMEDIATE_DIR = "$(PROJECT_DERIVED_FILE_DIR)/$(CONFIGURATION)"; + SHARED_INTERMEDIATE_DIR = "$(SYMROOT)/DerivedSources/$(CONFIGURATION)"; + }; + name = Release; + }; + F029E0D369FAFEA46BDAFCEE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + EXECUTABLE_PREFIX = lib; + GCC_PREPROCESSOR_DEFINITIONS = ( + "\"ANGLE_DISABLE_TRACE\"", + "\"ANGLE_COMPILE_OPTIMIZATION_LEVEL=D3DCOMPILE_OPTIMIZATION_LEVEL0\"", + ); + HEADER_SEARCH_PATHS = ( + ., + ../include, + ); + PRODUCT_NAME = translator_hlsl; + }; + name = Debug; + }; + FF01CDF4594E0FF9E581B319 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + EXECUTABLE_PREFIX = lib; + GCC_PREPROCESSOR_DEFINITIONS = ( + "\"ANGLE_DISABLE_TRACE\"", + "\"ANGLE_COMPILE_OPTIMIZATION_LEVEL=D3DCOMPILE_OPTIMIZATION_LEVEL0\"", + ); + HEADER_SEARCH_PATHS = ( + ., + ../include, + ); + PRODUCT_NAME = translator_common; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0E59F8FE4A8099E8DDCA4CE7 /* Build configuration list for PBXProject "build_angle" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9DC66E1FF9349CDCC8D52C46 /* Debug */, + C4546B14B0EB5EB8C5D39DC2 /* Release */, + ); + defaultConfigurationIsVisible = 1; + defaultConfigurationName = Debug; + }; + 34BB38E3A74418B2A063B49E /* Build configuration list for PBXNativeTarget "translator_common" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FF01CDF4594E0FF9E581B319 /* Debug */, + 4DA42A78D3B855C9CD8F658D /* Release */, + ); + defaultConfigurationIsVisible = 1; + defaultConfigurationName = Debug; + }; + 77CEFB7B40F05B0A804E6B2B /* Build configuration list for PBXAggregateTarget "All" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 322A8C62423B595E11BAD42D /* Debug */, + 4F851F5BA5FA43E9E0B9CB86 /* Release */, + ); + defaultConfigurationIsVisible = 1; + defaultConfigurationName = Debug; + }; + 8B8815CA2EFE60FD0C0361BF /* Build configuration list for PBXNativeTarget "translator_glsl" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 88ADC9285519A668808B51EE /* Debug */, + AF7C2CD10C6FEA076B141E6E /* Release */, + ); + defaultConfigurationIsVisible = 1; + defaultConfigurationName = Debug; + }; + C71E79C7829FD796CF621B44 /* Build configuration list for PBXNativeTarget "translator_hlsl" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F029E0D369FAFEA46BDAFCEE /* Debug */, + B096FAF032DB19AB637D38F0 /* Release */, + ); + defaultConfigurationIsVisible = 1; + defaultConfigurationName = Debug; + }; +/* 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 000000000..24c766bdf --- /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 000000000..4dd7327e7 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/common/debug.cpp @@ -0,0 +1,97 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// debug.cpp: Debugging utilities. + +#include "common/debug.h" + +#include <stdio.h> +#include <stdarg.h> +#include <d3d9.h> +#include <windows.h> + +namespace gl +{ + +typedef void (WINAPI *PerfOutputFunction)(D3DCOLOR, LPCWSTR); + +static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const char *format, va_list vararg) +{ +#if !defined(ANGLE_DISABLE_PERF) + if (perfActive()) + { + char message[4096]; + int len = vsprintf_s(message, format, vararg); + if (len < 0) + { + return; + } + + // There are no ASCII variants of these D3DPERF functions. + wchar_t wideMessage[4096]; + for (int i = 0; i < len; ++i) + { + wideMessage[i] = message[i]; + } + wideMessage[len] = 0; + + perfFunc(0, wideMessage); + } +#endif + +#if !defined(ANGLE_DISABLE_TRACE) +#if defined(NDEBUG) + if (traceFileDebugOnly) + { + return; + } +#endif + + FILE* file = fopen(TRACE_OUTPUT_FILE, "a"); + if (file) + { + vfprintf(file, format, vararg); + fclose(file); + } +#endif +} + +void trace(bool traceFileDebugOnly, const char *format, ...) +{ + va_list vararg; + va_start(vararg, format); + output(traceFileDebugOnly, D3DPERF_SetMarker, format, vararg); + va_end(vararg); +} + +bool perfActive() +{ +#if defined(ANGLE_DISABLE_PERF) + return false; +#else + static bool active = D3DPERF_GetStatus() != 0; + return active; +#endif +} + +ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...) +{ + va_list vararg; + va_start(vararg, format); + output(true, reinterpret_cast<PerfOutputFunction>(D3DPERF_BeginEvent), format, vararg); + va_end(vararg); +} + +ScopedPerfEventHelper::~ScopedPerfEventHelper() +{ +#if !defined(ANGLE_DISABLE_PERF) + if (perfActive()) + { + D3DPERF_EndEvent(); + } +#endif +} +} diff --git a/Source/ThirdParty/ANGLE/src/common/debug.h b/Source/ThirdParty/ANGLE/src/common/debug.h new file mode 100644 index 000000000..9828ecf03 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/common/debug.h @@ -0,0 +1,103 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// debug.h: Debugging utilities. + +#ifndef COMMON_DEBUG_H_ +#define COMMON_DEBUG_H_ + +#include <stdio.h> +#include <assert.h> + +#include "common/angleutils.h" + +#if !defined(TRACE_OUTPUT_FILE) +#define TRACE_OUTPUT_FILE "debug.txt" +#endif + +namespace gl +{ + // Outputs text to the debugging log + void trace(bool traceFileDebugOnly, const char *format, ...); + + // Returns whether D3DPERF is active. + bool perfActive(); + + // Pairs a D3D begin event with an end event. + class ScopedPerfEventHelper + { + public: + ScopedPerfEventHelper(const char* format, ...); + ~ScopedPerfEventHelper(); + + private: + DISALLOW_COPY_AND_ASSIGN(ScopedPerfEventHelper); + }; +} + +// A macro to output a trace of a function call and its arguments to the debugging log +#if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF) +#define TRACE(message, ...) (void(0)) +#else +#define TRACE(message, ...) gl::trace(true, "trace: %s(%d): "message"\n", __FUNCTION__, __LINE__, __VA_ARGS__) +#endif + +// A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing. +#if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF) +#define FIXME(message, ...) (void(0)) +#else +#define FIXME(message, ...) gl::trace(false, "fixme: %s(%d): "message"\n", __FUNCTION__, __LINE__, __VA_ARGS__) +#endif + +// A macro to output a function call and its arguments to the debugging log, in case of error. +#if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF) +#define ERR(message, ...) (void(0)) +#else +#define ERR(message, ...) gl::trace(false, "err: %s(%d): "message"\n", __FUNCTION__, __LINE__, __VA_ARGS__) +#endif + +// A macro to log a performance event around a scope. +#if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF) +#define EVENT(message, ...) (void(0)) +#else +#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__(__FUNCTION__ message "\n", __VA_ARGS__); +#endif + +// A macro asserting a condition and outputting failures to the debug log +#if !defined(NDEBUG) +#define ASSERT(expression) do { \ + if(!(expression)) \ + ERR("\t! Assert failed in %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \ + assert(expression); \ + } while(0) +#else +#define ASSERT(expression) (void(0)) +#endif + +// A macro to indicate unimplemented functionality +#if !defined(NDEBUG) +#define UNIMPLEMENTED() do { \ + FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__); \ + assert(false); \ + } while(0) +#else + #define UNIMPLEMENTED() FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__) +#endif + +// A macro for code which is not expected to be reached under valid assumptions +#if !defined(NDEBUG) +#define UNREACHABLE() do { \ + ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \ + assert(false); \ + } while(0) +#else + #define UNREACHABLE() ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__) +#endif + +// A macro functioning as a compile-time assert to validate constant conditions +#define META_ASSERT(condition) typedef int COMPILE_TIME_ASSERT_##__LINE__[static_cast<bool>(condition)?1:-1] + +#endif // COMMON_DEBUG_H_ diff --git a/Source/ThirdParty/ANGLE/src/common/version.h b/Source/ThirdParty/ANGLE/src/common/version.h new file mode 100644 index 000000000..4763332e7 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/common/version.h @@ -0,0 +1,10 @@ +#define MAJOR_VERSION 0 +#define MINOR_VERSION 0 +#define BUILD_VERSION 0 +#define BUILD_REVISION 696 + +#define STRINGIFY(x) #x +#define MACRO_STRINGIFY(x) STRINGIFY(x) + +#define REVISION_STRING MACRO_STRINGIFY(BUILD_REVISION) +#define VERSION_STRING MACRO_STRINGIFY(MAJOR_VERSION) "." MACRO_STRINGIFY(MINOR_VERSION) "." MACRO_STRINGIFY(BUILD_VERSION) "." MACRO_STRINGIFY(BUILD_REVISION) diff --git a/Source/ThirdParty/ANGLE/src/compiler/BaseTypes.h b/Source/ThirdParty/ANGLE/src/compiler/BaseTypes.h new file mode 100644 index 000000000..9f4a86020 --- /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 000000000..226bf8f0f --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/CodeGenGLSL.cpp @@ -0,0 +1,34 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/TranslatorGLSL.h" +#include "compiler/TranslatorESSL.h" + +// +// This function must be provided to create the actual +// compile object used by higher level code. It returns +// a subclass of TCompiler. +// +TCompiler* ConstructCompiler( + ShShaderType type, ShShaderSpec spec, ShShaderOutput output) +{ + switch (output) { + case SH_GLSL_OUTPUT: + return new TranslatorGLSL(type, spec); + case SH_ESSL_OUTPUT: + return new TranslatorESSL(type, spec); + default: + return NULL; + } +} + +// +// Delete the compiler made by ConstructCompiler +// +void DeleteCompiler(TCompiler* compiler) +{ + delete compiler; +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/CodeGenHLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/CodeGenHLSL.cpp new file mode 100644 index 000000000..f46ff66d4 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/CodeGenHLSL.cpp @@ -0,0 +1,31 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/TranslatorHLSL.h" + +// +// This function must be provided to create the actual +// compile object used by higher level code. It returns +// a subclass of TCompiler. +// +TCompiler* ConstructCompiler( + ShShaderType type, ShShaderSpec spec, ShShaderOutput output) +{ + switch (output) { + case SH_HLSL_OUTPUT: + return new TranslatorHLSL(type, spec); + default: + return NULL; + } +} + +// +// Delete the compiler made by ConstructCompiler +// +void DeleteCompiler(TCompiler* compiler) +{ + delete compiler; +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/Common.h b/Source/ThirdParty/ANGLE/src/compiler/Common.h new file mode 100644 index 000000000..27a559829 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/Common.h @@ -0,0 +1,89 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _COMMON_INCLUDED_ +#define _COMMON_INCLUDED_ + +#include <map> +#include <sstream> +#include <string> +#include <vector> + +#include "compiler/PoolAlloc.h" + +// We need two pieces of information to report errors/warnings - string and +// line number. We encode these into a single int so that it can be easily +// incremented/decremented by lexer. The right SOURCE_LOC_LINE_SIZE bits store +// line number while the rest store the string number. Since the shaders are +// usually small, we should not run out of memory. SOURCE_LOC_LINE_SIZE +// can be increased to alleviate this issue. +typedef int TSourceLoc; +const unsigned int SOURCE_LOC_LINE_SIZE = 16; // in bits. +const unsigned int SOURCE_LOC_LINE_MASK = (1 << SOURCE_LOC_LINE_SIZE) - 1; + +inline TSourceLoc EncodeSourceLoc(int string, int line) { + return (string << SOURCE_LOC_LINE_SIZE) | (line & SOURCE_LOC_LINE_MASK); +} + +inline void DecodeSourceLoc(TSourceLoc loc, int* string, int* line) { + if (string) *string = loc >> SOURCE_LOC_LINE_SIZE; + if (line) *line = loc & SOURCE_LOC_LINE_MASK; +} + +// +// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. +// +#define POOL_ALLOCATOR_NEW_DELETE(A) \ + void* operator new(size_t s) { return (A).allocate(s); } \ + void* operator new(size_t, void *_Where) { return (_Where); } \ + void operator delete(void*) { } \ + void operator delete(void *, void *) { } \ + void* operator new[](size_t s) { return (A).allocate(s); } \ + void* operator new[](size_t, void *_Where) { return (_Where); } \ + void operator delete[](void*) { } \ + void operator delete[](void *, void *) { } + +// +// Pool version of string. +// +typedef pool_allocator<char> TStringAllocator; +typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TString; +typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream; +inline TString* NewPoolTString(const char* s) +{ + void* memory = GlobalPoolAllocator.allocate(sizeof(TString)); + return new(memory) TString(s); +} + +// +// Persistent string memory. Should only be used for strings that survive +// across compiles. +// +#define TPersistString std::string +#define TPersistStringStream std::ostringstream + +// +// Pool allocator versions of vectors, lists, and maps +// +template <class T> class TVector : public std::vector<T, pool_allocator<T> > { +public: + typedef typename std::vector<T, pool_allocator<T> >::size_type size_type; + TVector() : std::vector<T, pool_allocator<T> >() {} + TVector(const pool_allocator<T>& a) : std::vector<T, pool_allocator<T> >(a) {} + TVector(size_type i): std::vector<T, pool_allocator<T> >(i) {} +}; + +template <class K, class D, class CMP = std::less<K> > +class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D> > > { +public: + typedef pool_allocator<std::pair<const K, D> > tAllocator; + + TMap() : std::map<K, D, CMP, tAllocator>() {} + // use correct two-stage name lookup supported in gcc 3.4 and above + TMap(const tAllocator& a) : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a) {} +}; + +#endif // _COMMON_INCLUDED_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/Compiler.cpp b/Source/ThirdParty/ANGLE/src/compiler/Compiler.cpp new file mode 100644 index 000000000..5d86a3ec0 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/Compiler.cpp @@ -0,0 +1,224 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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/Initialize.h" +#include "compiler/ParseHelper.h" +#include "compiler/ShHandle.h" +#include "compiler/ValidateLimitations.h" +#include "compiler/MapLongVariableNames.h" + +namespace { +bool InitializeSymbolTable( + const TBuiltInStrings& builtInStrings, + ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources, + TInfoSink& infoSink, TSymbolTable& symbolTable) +{ + TIntermediate intermediate(infoSink); + TExtensionBehavior extBehavior; + // The builtins deliberately don't specify precisions for the function + // arguments and return types. For that reason we don't try to check them. + TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, 0, false, NULL, infoSink); + + GlobalParseContext = &parseContext; + + assert(symbolTable.isEmpty()); + // + // Parse the built-ins. This should only happen once per + // language symbol table. + // + // Push the symbol table to give it an initial scope. This + // push should not have a corresponding pop, so that built-ins + // are preserved, and the test for an empty table fails. + // + symbolTable.push(); + + for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i) + { + const char* builtInShaders = i->c_str(); + int builtInLengths = static_cast<int>(i->size()); + if (builtInLengths <= 0) + continue; + + if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0) + { + infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins"); + return false; + } + } + + IdentifyBuiltIns(type, spec, resources, symbolTable); + + return true; +} + +class TScopedPoolAllocator { +public: + TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop) + : mAllocator(allocator), mPushPopAllocator(pushPop) { + if (mPushPopAllocator) mAllocator->push(); + SetGlobalPoolAllocator(mAllocator); + } + ~TScopedPoolAllocator() { + SetGlobalPoolAllocator(NULL); + if (mPushPopAllocator) mAllocator->pop(); + } + +private: + TPoolAllocator* mAllocator; + bool mPushPopAllocator; +}; +} // namespace + +TShHandleBase::TShHandleBase() { + allocator.push(); + SetGlobalPoolAllocator(&allocator); +} + +TShHandleBase::~TShHandleBase() { + SetGlobalPoolAllocator(NULL); + allocator.popAll(); +} + +TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec) + : shaderType(type), + shaderSpec(spec) +{ +} + +TCompiler::~TCompiler() +{ +} + +bool TCompiler::Init(const ShBuiltInResources& resources) +{ + TScopedPoolAllocator scopedAlloc(&allocator, false); + + // Generate built-in symbol table. + if (!InitBuiltInSymbolTable(resources)) + return false; + InitExtensionBehavior(resources, extensionBehavior); + + return true; +} + +bool TCompiler::compile(const char* const shaderStrings[], + const int numStrings, + int compileOptions) +{ + TScopedPoolAllocator scopedAlloc(&allocator, true); + clearResults(); + + if (numStrings == 0) + return true; + + // If compiling for WebGL, validate loop and indexing as well. + if (shaderSpec == SH_WEBGL_SPEC) + compileOptions |= SH_VALIDATE_LOOP_INDEXING; + + // First string is path of source file if flag is set. The actual source follows. + const char* sourcePath = NULL; + int firstSource = 0; + if (compileOptions & SH_SOURCE_PATH) + { + sourcePath = shaderStrings[0]; + ++firstSource; + } + + TIntermediate intermediate(infoSink); + TParseContext parseContext(symbolTable, extensionBehavior, intermediate, + shaderType, shaderSpec, compileOptions, true, + sourcePath, infoSink); + GlobalParseContext = &parseContext; + + // We preserve symbols at the built-in level from compile-to-compile. + // Start pushing the user-defined symbols at global level. + symbolTable.push(); + if (!symbolTable.atGlobalLevel()) + infoSink.info.message(EPrefixInternalError, "Wrong symbol table level"); + + // Parse shader. + bool success = + (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) && + (parseContext.treeRoot != NULL); + if (success) { + TIntermNode* root = parseContext.treeRoot; + success = intermediate.postProcess(root); + + if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING)) + success = validateLimitations(root); + + // Call mapLongVariableNames() before collectAttribsUniforms() so in + // collectAttribsUniforms() we already have the mapped symbol names and + // we could composite mapped and original variable names. + if (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) + mapLongVariableNames(root); + + if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) + collectAttribsUniforms(root); + + if (success && (compileOptions & SH_INTERMEDIATE_TREE)) + intermediate.outputTree(root); + + if (success && (compileOptions & SH_OBJECT_CODE)) + translate(root); + } + + // Cleanup memory. + intermediate.remove(parseContext.treeRoot); + // Ensure symbol table is returned to the built-in level, + // throwing away all but the built-ins. + while (!symbolTable.atBuiltInLevel()) + symbolTable.pop(); + + return success; +} + +bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources) +{ + TBuiltIns builtIns; + + builtIns.initialize(shaderType, shaderSpec, resources); + return InitializeSymbolTable(builtIns.getBuiltInStrings(), + shaderType, shaderSpec, resources, infoSink, symbolTable); +} + +void TCompiler::clearResults() +{ + infoSink.info.erase(); + infoSink.obj.erase(); + infoSink.debug.erase(); + + attribs.clear(); + uniforms.clear(); +} + +bool TCompiler::validateLimitations(TIntermNode* root) { + ValidateLimitations validate(shaderType, infoSink.info); + root->traverse(&validate); + return validate.numErrors() == 0; +} + +void TCompiler::collectAttribsUniforms(TIntermNode* root) +{ + CollectAttribsUniforms collect(attribs, uniforms); + root->traverse(&collect); +} + +void TCompiler::mapLongVariableNames(TIntermNode* root) +{ + MapLongVariableNames map(varyingLongNameMap); + root->traverse(&map); +} + +int TCompiler::getMappedNameMaxLength() const +{ + return MAX_IDENTIFIER_NAME_SIZE + 1; +} + +const TExtensionBehavior& TCompiler::getExtensionBehavior() const +{ + return extensionBehavior; +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/ConstantUnion.h b/Source/ThirdParty/ANGLE/src/compiler/ConstantUnion.h new file mode 100644 index 000000000..d28a11b8b --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/ConstantUnion.h @@ -0,0 +1,258 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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 + { + return i == iConst; + } + + bool operator==(const float f) const + { + return f == fConst; + } + + bool operator==(const bool b) const + { + return b == bConst; + } + + bool operator==(const ConstantUnion& constant) const + { + if (constant.type != type) + return false; + + switch (type) { + case EbtInt: + return constant.iConst == iConst; + case EbtFloat: + return constant.fConst == fConst; + case EbtBool: + return constant.bConst == bConst; + default: + return false; + } + + return false; + } + + bool operator!=(const int i) const + { + return !operator==(i); + } + + bool operator!=(const float f) const + { + return !operator==(f); + } + + bool operator!=(const bool b) const + { + return !operator==(b); + } + + bool operator!=(const ConstantUnion& constant) const + { + return !operator==(constant); + } + + bool operator>(const ConstantUnion& constant) const + { + assert(type == constant.type); + switch (type) { + case EbtInt: + return iConst > constant.iConst; + case EbtFloat: + return fConst > constant.fConst; + default: + return false; // Invalid operation, handled at semantic analysis + } + + return false; + } + + bool operator<(const ConstantUnion& constant) const + { + assert(type == constant.type); + switch (type) { + case EbtInt: + return iConst < constant.iConst; + case EbtFloat: + return fConst < constant.fConst; + default: + return false; // Invalid operation, handled at semantic analysis + } + + return false; + } + + ConstantUnion operator+(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst + constant.iConst); break; + case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator-(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst - constant.iConst); break; + case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator*(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst * constant.iConst); break; + case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator%(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst % constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator>>(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator<<(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator&(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator|(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst | constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator^(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator&&(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst && constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator||(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst || constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TBasicType getType() const { return type; } +private: + + union { + int iConst; // used for ivec, scalar ints + bool bConst; // used for bvec, scalar bools + float fConst; // used for vec, mat, scalar floats + } ; + + TBasicType type; +}; + +#endif // _CONSTANT_UNION_INCLUDED_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/ExtensionBehavior.h b/Source/ThirdParty/ANGLE/src/compiler/ExtensionBehavior.h new file mode 100644 index 000000000..ab5a0a53b --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/ExtensionBehavior.h @@ -0,0 +1,37 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _EXTENSION_BEHAVIOR_INCLUDED_ +#define _EXTENSION_BEHAVIOR_INCLUDED_ + +#include "compiler/Common.h" + +typedef enum { + EBhRequire, + EBhEnable, + EBhWarn, + EBhDisable +} TBehavior; + +inline const char* getBehaviorString(TBehavior b) +{ + switch(b) { + case EBhRequire: + return "require"; + case EBhEnable: + return "enable"; + case EBhWarn: + return "warn"; + case EBhDisable: + return "disable"; + default: + return NULL; + } +} + +typedef TMap<TString, TBehavior> TExtensionBehavior; + +#endif // _EXTENSION_TABLE_INCLUDED_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/ForLoopUnroll.cpp b/Source/ThirdParty/ANGLE/src/compiler/ForLoopUnroll.cpp new file mode 100644 index 000000000..d631af44f --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/ForLoopUnroll.cpp @@ -0,0 +1,172 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/ForLoopUnroll.h" + +void ForLoopUnroll::FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info) +{ + ASSERT(node->getType() == ELoopFor); + ASSERT(node->getUnrollFlag()); + + TIntermNode* init = node->getInit(); + ASSERT(init != NULL); + TIntermAggregate* decl = init->getAsAggregate(); + ASSERT((decl != NULL) && (decl->getOp() == EOpDeclaration)); + TIntermSequence& declSeq = decl->getSequence(); + ASSERT(declSeq.size() == 1); + TIntermBinary* declInit = declSeq[0]->getAsBinaryNode(); + ASSERT((declInit != NULL) && (declInit->getOp() == EOpInitialize)); + TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode(); + ASSERT(symbol != NULL); + ASSERT(symbol->getBasicType() == EbtInt); + + info.id = symbol->getId(); + + ASSERT(declInit->getRight() != NULL); + TIntermConstantUnion* initNode = declInit->getRight()->getAsConstantUnion(); + ASSERT(initNode != NULL); + + info.initValue = evaluateIntConstant(initNode); + info.currentValue = info.initValue; + + TIntermNode* cond = node->getCondition(); + ASSERT(cond != NULL); + TIntermBinary* binOp = cond->getAsBinaryNode(); + ASSERT(binOp != NULL); + ASSERT(binOp->getRight() != NULL); + ASSERT(binOp->getRight()->getAsConstantUnion() != NULL); + + info.incrementValue = getLoopIncrement(node); + info.stopValue = evaluateIntConstant( + binOp->getRight()->getAsConstantUnion()); + info.op = binOp->getOp(); +} + +void ForLoopUnroll::Step() +{ + ASSERT(mLoopIndexStack.size() > 0); + TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1]; + info.currentValue += info.incrementValue; +} + +bool ForLoopUnroll::SatisfiesLoopCondition() +{ + ASSERT(mLoopIndexStack.size() > 0); + TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1]; + // Relational operator is one of: > >= < <= == or !=. + switch (info.op) { + case EOpEqual: + return (info.currentValue == info.stopValue); + case EOpNotEqual: + return (info.currentValue != info.stopValue); + case EOpLessThan: + return (info.currentValue < info.stopValue); + case EOpGreaterThan: + return (info.currentValue > info.stopValue); + case EOpLessThanEqual: + return (info.currentValue <= info.stopValue); + case EOpGreaterThanEqual: + return (info.currentValue >= info.stopValue); + default: + UNREACHABLE(); + } + return false; +} + +bool ForLoopUnroll::NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol) +{ + for (TVector<TLoopIndexInfo>::iterator i = mLoopIndexStack.begin(); + i != mLoopIndexStack.end(); + ++i) { + if (i->id == symbol->getId()) + return true; + } + return false; +} + +int ForLoopUnroll::GetLoopIndexValue(TIntermSymbol* symbol) +{ + for (TVector<TLoopIndexInfo>::iterator i = mLoopIndexStack.begin(); + i != mLoopIndexStack.end(); + ++i) { + if (i->id == symbol->getId()) + return i->currentValue; + } + UNREACHABLE(); + return false; +} + +void ForLoopUnroll::Push(TLoopIndexInfo& info) +{ + mLoopIndexStack.push_back(info); +} + +void ForLoopUnroll::Pop() +{ + mLoopIndexStack.pop_back(); +} + +int ForLoopUnroll::getLoopIncrement(TIntermLoop* node) +{ + TIntermNode* expr = node->getExpression(); + ASSERT(expr != NULL); + // for expression has one of the following forms: + // loop_index++ + // loop_index-- + // loop_index += constant_expression + // loop_index -= constant_expression + // ++loop_index + // --loop_index + // The last two forms are not specified in the spec, but I am assuming + // its an oversight. + TIntermUnary* unOp = expr->getAsUnaryNode(); + TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode(); + + TOperator op = EOpNull; + TIntermConstantUnion* incrementNode = NULL; + if (unOp != NULL) { + op = unOp->getOp(); + } else if (binOp != NULL) { + op = binOp->getOp(); + ASSERT(binOp->getRight() != NULL); + incrementNode = binOp->getRight()->getAsConstantUnion(); + ASSERT(incrementNode != NULL); + } + + int increment = 0; + // The operator is one of: ++ -- += -=. + switch (op) { + case EOpPostIncrement: + case EOpPreIncrement: + ASSERT((unOp != NULL) && (binOp == NULL)); + increment = 1; + break; + case EOpPostDecrement: + case EOpPreDecrement: + ASSERT((unOp != NULL) && (binOp == NULL)); + increment = -1; + break; + case EOpAddAssign: + ASSERT((unOp == NULL) && (binOp != NULL)); + increment = evaluateIntConstant(incrementNode); + break; + case EOpSubAssign: + ASSERT((unOp == NULL) && (binOp != NULL)); + increment = - evaluateIntConstant(incrementNode); + break; + default: + ASSERT(false); + } + + return increment; +} + +int ForLoopUnroll::evaluateIntConstant(TIntermConstantUnion* node) +{ + ASSERT((node != NULL) && (node->getUnionArrayPointer() != NULL)); + return node->getUnionArrayPointer()->getIConst(); +} + diff --git a/Source/ThirdParty/ANGLE/src/compiler/ForLoopUnroll.h b/Source/ThirdParty/ANGLE/src/compiler/ForLoopUnroll.h new file mode 100644 index 000000000..b2b2b58c1 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/ForLoopUnroll.h @@ -0,0 +1,46 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/intermediate.h" + +struct TLoopIndexInfo { + int id; + int initValue; + int stopValue; + int incrementValue; + TOperator op; + int currentValue; +}; + +class ForLoopUnroll { +public: + ForLoopUnroll() { } + + void FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info); + + // Update the info.currentValue for the next loop iteration. + void Step(); + + // Return false if loop condition is no longer satisfied. + bool SatisfiesLoopCondition(); + + // Check if the symbol is the index of a loop that's unrolled. + bool NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol); + + // Return the current value of a given loop index symbol. + int GetLoopIndexValue(TIntermSymbol* symbol); + + void Push(TLoopIndexInfo& info); + void Pop(); + +private: + int getLoopIncrement(TIntermLoop* node); + + int evaluateIntConstant(TIntermConstantUnion* node); + + TVector<TLoopIndexInfo> mLoopIndexStack; +}; + diff --git a/Source/ThirdParty/ANGLE/src/compiler/InfoSink.cpp b/Source/ThirdParty/ANGLE/src/compiler/InfoSink.cpp new file mode 100644 index 000000000..ba32f781f --- /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 = 0, line = 0; + DecodeSourceLoc(loc, &string, &line); + + TPersistStringStream stream; + if (line) + stream << string << ":" << line; + else + stream << string << ":? "; + stream << ": "; + + sink.append(stream.str()); +} + +void TInfoSinkBase::message(TPrefixType message, const char* s) { + prefix(message); + sink.append(s); + sink.append("\n"); +} + +void TInfoSinkBase::message(TPrefixType message, const char* s, TSourceLoc loc) { + prefix(message); + location(loc); + sink.append(s); + sink.append("\n"); +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/InfoSink.h b/Source/ThirdParty/ANGLE/src/compiler/InfoSink.h new file mode 100644 index 000000000..e2224e918 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/InfoSink.h @@ -0,0 +1,115 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _INFOSINK_INCLUDED_ +#define _INFOSINK_INCLUDED_ + +#include <math.h> +#include "compiler/Common.h" + +// Returns the fractional part of the given floating-point number. +inline float fractionalPart(float f) { + float intPart = 0.0f; + return modff(f, &intPart); +} + +// +// TPrefixType is used to centralize how info log messages start. +// See below. +// +enum TPrefixType { + EPrefixNone, + EPrefixWarning, + EPrefixError, + EPrefixInternalError, + EPrefixUnimplemented, + EPrefixNote +}; + +// +// Encapsulate info logs for all objects that have them. +// +// The methods are a general set of tools for getting a variety of +// messages and types inserted into the log. +// +class TInfoSinkBase { +public: + TInfoSinkBase() {} + + template <typename T> + TInfoSinkBase& operator<<(const T& t) { + TPersistStringStream stream; + stream << t; + sink.append(stream.str()); + return *this; + } + // Override << operator for specific types. It is faster to append strings + // and characters directly to the sink. + TInfoSinkBase& operator<<(char c) { + sink.append(1, c); + return *this; + } + TInfoSinkBase& operator<<(const char* str) { + sink.append(str); + return *this; + } + TInfoSinkBase& operator<<(const TPersistString& str) { + sink.append(str); + return *this; + } + TInfoSinkBase& operator<<(const TString& str) { + sink.append(str.c_str()); + return *this; + } + // Make sure floats are written with correct precision. + TInfoSinkBase& operator<<(float f) { + // Make sure that at least one decimal point is written. If a number + // does not have a fractional part, the default precision format does + // not write the decimal portion which gets interpreted as integer by + // the compiler. + TPersistStringStream stream; + if (fractionalPart(f) == 0.0f) { + stream.precision(1); + stream << std::showpoint << std::fixed << f; + } else { + stream.unsetf(std::ios::fixed); + stream.unsetf(std::ios::scientific); + stream.precision(8); + stream << f; + } + sink.append(stream.str()); + return *this; + } + // Write boolean values as their names instead of integral value. + TInfoSinkBase& operator<<(bool b) { + const char* str = b ? "true" : "false"; + sink.append(str); + return *this; + } + + void erase() { sink.clear(); } + int size() { return static_cast<int>(sink.size()); } + + const TPersistString& str() const { return sink; } + const char* c_str() const { return sink.c_str(); } + + void prefix(TPrefixType message); + void location(TSourceLoc loc); + void message(TPrefixType message, const char* s); + void message(TPrefixType message, const char* s, TSourceLoc loc); + +private: + TPersistString sink; +}; + +class TInfoSink { +public: + TInfoSinkBase info; + TInfoSinkBase debug; + TInfoSinkBase obj; +}; + +#endif // _INFOSINK_INCLUDED_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/Initialize.cpp b/Source/ThirdParty/ANGLE/src/compiler/Initialize.cpp new file mode 100644 index 000000000..74a2de36e --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/Initialize.cpp @@ -0,0 +1,629 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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);")); + + // + // Noise functions. + // + //s.append(TString("float noise1(float x);")); + //s.append(TString("float noise1(vec2 x);")); + //s.append(TString("float noise1(vec3 x);")); + //s.append(TString("float noise1(vec4 x);")); + + //s.append(TString("vec2 noise2(float x);")); + //s.append(TString("vec2 noise2(vec2 x);")); + //s.append(TString("vec2 noise2(vec3 x);")); + //s.append(TString("vec2 noise2(vec4 x);")); + + //s.append(TString("vec3 noise3(float x);")); + //s.append(TString("vec3 noise3(vec2 x);")); + //s.append(TString("vec3 noise3(vec3 x);")); + //s.append(TString("vec3 noise3(vec4 x);")); + + //s.append(TString("vec4 noise4(float x);")); + //s.append(TString("vec4 noise4(vec2 x);")); + //s.append(TString("vec4 noise4(vec3 x);")); + //s.append(TString("vec4 noise4(vec4 x);")); + + return s; +} + +//============================================================================ +// +// Prototypes for built-in functions seen by vertex shaders only. +// +//============================================================================ +static TString BuiltInFunctionsVertex(const ShBuiltInResources& resources) +{ + TString s; + + // + // Geometric Functions. + // + //s.append(TString("vec4 ftransform();")); + + // + // Texture Functions. + // + s.append(TString("vec4 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);")); + + s.append(TString("vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);")); + s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);")); + s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);")); + s.append(TString("vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);")); + + return s; +} + +//============================================================================ +// +// Prototypes for built-in functions seen by fragment shaders only. +// +//============================================================================ +static TString BuiltInFunctionsFragment(const ShBuiltInResources& resources) +{ + TString s; + + // + // Texture Functions. + // + s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord);")); + 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);")); + + s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord, float bias);")); + s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);")); + s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias);")); + s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord, float bias);")); + + if (resources.OES_standard_derivatives) { + s.append(TString("float dFdx(float p);")); + s.append(TString("vec2 dFdx(vec2 p);")); + s.append(TString("vec3 dFdx(vec3 p);")); + s.append(TString("vec4 dFdx(vec4 p);")); + + s.append(TString("float dFdy(float p);")); + s.append(TString("vec2 dFdy(vec2 p);")); + s.append(TString("vec3 dFdy(vec3 p);")); + s.append(TString("vec4 dFdy(vec4 p);")); + + s.append(TString("float fwidth(float p);")); + s.append(TString("vec2 fwidth(vec2 p);")); + s.append(TString("vec3 fwidth(vec3 p);")); + s.append(TString("vec4 fwidth(vec4 p);")); + } + + return s; +} + +//============================================================================ +// +// Standard uniforms. +// +//============================================================================ +static TString StandardUniforms() +{ + TString s; + + // + // Depth range in window coordinates + // + s.append(TString("struct gl_DepthRangeParameters {")); + s.append(TString(" highp float near;")); // n + s.append(TString(" highp float far;")); // f + s.append(TString(" highp float diff;")); // f - n + s.append(TString("};")); + s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;")); + + return s; +} + +//============================================================================ +// +// Default precision for vertex shaders. +// +//============================================================================ +static TString DefaultPrecisionVertex() +{ + TString s; + + s.append(TString("precision highp int;")); + s.append(TString("precision highp float;")); + + return s; +} + +//============================================================================ +// +// Default precision for fragment shaders. +// +//============================================================================ +static TString DefaultPrecisionFragment() +{ + TString s; + + s.append(TString("precision mediump int;")); + // No default precision for float in fragment shaders + + return s; +} + +//============================================================================ +// +// Implementation dependent built-in constants. +// +//============================================================================ +static TString BuiltInConstants(const ShBuiltInResources &resources) +{ + TStringStream s; + + s << "const int gl_MaxVertexAttribs = " << resources.MaxVertexAttribs << ";"; + s << "const int gl_MaxVertexUniformVectors = " << resources.MaxVertexUniformVectors << ";"; + + s << "const int gl_MaxVaryingVectors = " << resources.MaxVaryingVectors << ";"; + s << "const int gl_MaxVertexTextureImageUnits = " << resources.MaxVertexTextureImageUnits << ";"; + s << "const int gl_MaxCombinedTextureImageUnits = " << resources.MaxCombinedTextureImageUnits << ";"; + s << "const int gl_MaxTextureImageUnits = " << resources.MaxTextureImageUnits << ";"; + s << "const int gl_MaxFragmentUniformVectors = " << resources.MaxFragmentUniformVectors << ";"; + s << "const int gl_MaxDrawBuffers = " << resources.MaxDrawBuffers << ";"; + + return s.str(); +} + +void TBuiltIns::initialize(ShShaderType type, ShShaderSpec spec, + const ShBuiltInResources& resources) +{ + switch (type) { + case SH_FRAGMENT_SHADER: + builtInStrings.push_back(DefaultPrecisionFragment()); + builtInStrings.push_back(BuiltInFunctionsCommon()); + builtInStrings.push_back(BuiltInFunctionsFragment(resources)); + builtInStrings.push_back(StandardUniforms()); + break; + + case SH_VERTEX_SHADER: + builtInStrings.push_back(DefaultPrecisionVertex()); + builtInStrings.push_back(BuiltInFunctionsCommon()); + builtInStrings.push_back(BuiltInFunctionsVertex(resources)); + builtInStrings.push_back(StandardUniforms()); + break; + + default: assert(false && "Language not supported"); + } + + builtInStrings.push_back(BuiltInConstants(resources)); +} + +void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, + const ShBuiltInResources& resources, + TSymbolTable& symbolTable) +{ + // + // First, insert some special built-in variables that are not in + // the built-in header files. + // + switch(type) { + case SH_FRAGMENT_SHADER: + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4))); + symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1))); + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4))); + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4))); + symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2))); + break; + + case SH_VERTEX_SHADER: + symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4))); + symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EbpMedium, EvqPointSize, 1))); + break; + + default: assert(false && "Language not supported"); + } + + // + // Next, identify which built-ins from the already loaded headers have + // a mapping to an operator. Those that are not identified as such are + // expected to be resolved through a library of functions, versus as + // operations. + // + symbolTable.relateToOperator("not", EOpVectorLogicalNot); + + symbolTable.relateToOperator("matrixCompMult", EOpMul); + + symbolTable.relateToOperator("equal", EOpVectorEqual); + symbolTable.relateToOperator("notEqual", EOpVectorNotEqual); + symbolTable.relateToOperator("lessThan", EOpLessThan); + symbolTable.relateToOperator("greaterThan", EOpGreaterThan); + symbolTable.relateToOperator("lessThanEqual", EOpLessThanEqual); + symbolTable.relateToOperator("greaterThanEqual", EOpGreaterThanEqual); + + symbolTable.relateToOperator("radians", EOpRadians); + symbolTable.relateToOperator("degrees", EOpDegrees); + symbolTable.relateToOperator("sin", EOpSin); + symbolTable.relateToOperator("cos", EOpCos); + symbolTable.relateToOperator("tan", EOpTan); + symbolTable.relateToOperator("asin", EOpAsin); + symbolTable.relateToOperator("acos", EOpAcos); + symbolTable.relateToOperator("atan", EOpAtan); + + symbolTable.relateToOperator("pow", EOpPow); + symbolTable.relateToOperator("exp2", EOpExp2); + symbolTable.relateToOperator("log", EOpLog); + symbolTable.relateToOperator("exp", EOpExp); + symbolTable.relateToOperator("log2", EOpLog2); + symbolTable.relateToOperator("sqrt", EOpSqrt); + symbolTable.relateToOperator("inversesqrt", EOpInverseSqrt); + + symbolTable.relateToOperator("abs", EOpAbs); + symbolTable.relateToOperator("sign", EOpSign); + symbolTable.relateToOperator("floor", EOpFloor); + symbolTable.relateToOperator("ceil", EOpCeil); + symbolTable.relateToOperator("fract", EOpFract); + symbolTable.relateToOperator("mod", EOpMod); + symbolTable.relateToOperator("min", EOpMin); + symbolTable.relateToOperator("max", EOpMax); + symbolTable.relateToOperator("clamp", EOpClamp); + symbolTable.relateToOperator("mix", EOpMix); + symbolTable.relateToOperator("step", EOpStep); + symbolTable.relateToOperator("smoothstep", EOpSmoothStep); + + symbolTable.relateToOperator("length", EOpLength); + symbolTable.relateToOperator("distance", EOpDistance); + symbolTable.relateToOperator("dot", EOpDot); + symbolTable.relateToOperator("cross", EOpCross); + symbolTable.relateToOperator("normalize", EOpNormalize); + symbolTable.relateToOperator("faceforward", EOpFaceForward); + symbolTable.relateToOperator("reflect", EOpReflect); + symbolTable.relateToOperator("refract", EOpRefract); + + symbolTable.relateToOperator("any", EOpAny); + symbolTable.relateToOperator("all", EOpAll); + + // Map language-specific operators. + switch(type) { + case SH_VERTEX_SHADER: + break; + case SH_FRAGMENT_SHADER: + if (resources.OES_standard_derivatives) { + symbolTable.relateToOperator("dFdx", EOpDFdx); + symbolTable.relateToOperator("dFdy", EOpDFdy); + symbolTable.relateToOperator("fwidth", EOpFwidth); + + symbolTable.relateToExtension("dFdx", "GL_OES_standard_derivatives"); + symbolTable.relateToExtension("dFdy", "GL_OES_standard_derivatives"); + symbolTable.relateToExtension("fwidth", "GL_OES_standard_derivatives"); + } + break; + default: break; + } + + // Finally add resource-specific variables. + switch(type) { + case SH_FRAGMENT_SHADER: { + // Set up gl_FragData. The array size. + TType fragData(EbtFloat, EbpMedium, EvqFragColor, 4, false, true); + fragData.setArraySize(resources.MaxDrawBuffers); + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData)); + } + break; + default: break; + } +} + +void InitExtensionBehavior(const ShBuiltInResources& resources, + TExtensionBehavior& extBehavior) +{ + if (resources.OES_standard_derivatives) + extBehavior["GL_OES_standard_derivatives"] = EBhDisable; +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/Initialize.h b/Source/ThirdParty/ANGLE/src/compiler/Initialize.h new file mode 100644 index 000000000..8b0adc6b4 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/Initialize.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _INITIALIZE_INCLUDED_ +#define _INITIALIZE_INCLUDED_ + +#include "compiler/Common.h" +#include "compiler/ShHandle.h" +#include "compiler/SymbolTable.h" + +typedef TVector<TString> TBuiltInStrings; + +class TBuiltIns { +public: + POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + + void initialize(ShShaderType type, ShShaderSpec spec, + const ShBuiltInResources& resources); + const TBuiltInStrings& getBuiltInStrings() { return builtInStrings; } + +protected: + TBuiltInStrings builtInStrings; +}; + +void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, + const ShBuiltInResources& resources, + TSymbolTable& symbolTable); + +void InitExtensionBehavior(const ShBuiltInResources& resources, + TExtensionBehavior& extensionBehavior); + +#endif // _INITIALIZE_INCLUDED_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/InitializeDll.cpp b/Source/ThirdParty/ANGLE/src/compiler/InitializeDll.cpp new file mode 100644 index 000000000..8763cfeea --- /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 000000000..857238eea --- /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 000000000..842a45281 --- /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 000000000..760fd09d5 --- /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 000000000..a13877f18 --- /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(expr) + { + expr->traverse(it); + } + + if(body) + { + body->traverse(it); + } + + if(cond) + { + cond->traverse(it); + } + } + else + { + if(cond) + { + cond->traverse(it); + } + + if(body) + { + body->traverse(it); + } + + if(expr) + { + expr->traverse(it); + } + } + + it->decrementDepth(); + } + + if(visit && it->postVisit) + { + it->visitLoop(PostVisit, this); + } +} + +// +// Traverse a branch node. Same comments in binary node apply here. +// +void TIntermBranch::traverse(TIntermTraverser* it) +{ + bool visit = true; + + if (it->preVisit) + visit = it->visitBranch(PreVisit, this); + + if (visit && expression) { + it->incrementDepth(); + expression->traverse(it); + it->decrementDepth(); + } + + if (visit && it->postVisit) + it->visitBranch(PostVisit, this); +} + diff --git a/Source/ThirdParty/ANGLE/src/compiler/Intermediate.cpp b/Source/ThirdParty/ANGLE/src/compiler/Intermediate.cpp new file mode 100644 index 000000000..e1e8da25a --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/Intermediate.cpp @@ -0,0 +1,1454 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// +// Build the intermediate representation. +// + +#include <float.h> +#include <limits.h> +#include <algorithm> + +#include "compiler/localintermediate.h" +#include "compiler/QualifierAlive.h" +#include "compiler/RemoveTree.h" + +bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray); + +static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){ + return left > right ? left : right; +} + +const char* getOperatorString(TOperator op) { + switch (op) { + case EOpInitialize: return "="; + case EOpAssign: return "="; + case EOpAddAssign: return "+="; + case EOpSubAssign: return "-="; + case EOpDivAssign: return "/="; + + // Fall-through. + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: return "*="; + + // Fall-through. + case EOpIndexDirect: + case EOpIndexIndirect: return "[]"; + + case EOpIndexDirectStruct: return "."; + case EOpVectorSwizzle: return "."; + case EOpAdd: return "+"; + case EOpSub: return "-"; + case EOpMul: return "*"; + case EOpDiv: return "/"; + case EOpMod: UNIMPLEMENTED(); break; + case EOpEqual: return "=="; + case EOpNotEqual: return "!="; + case EOpLessThan: return "<"; + case EOpGreaterThan: return ">"; + case EOpLessThanEqual: return "<="; + case EOpGreaterThanEqual: return ">="; + + // Fall-through. + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpMatrixTimesMatrix: return "*"; + + case EOpLogicalOr: return "||"; + case EOpLogicalXor: return "^^"; + case EOpLogicalAnd: return "&&"; + case EOpNegative: return "-"; + case EOpVectorLogicalNot: return "not"; + case EOpLogicalNot: return "!"; + case EOpPostIncrement: return "++"; + case EOpPostDecrement: return "--"; + case EOpPreIncrement: return "++"; + case EOpPreDecrement: return "--"; + + // Fall-through. + case EOpConvIntToBool: + case EOpConvFloatToBool: return "bool"; + + // Fall-through. + case EOpConvBoolToFloat: + case EOpConvIntToFloat: return "float"; + + // Fall-through. + case EOpConvFloatToInt: + case EOpConvBoolToInt: return "int"; + + case EOpRadians: return "radians"; + case EOpDegrees: return "degrees"; + case EOpSin: return "sin"; + case EOpCos: return "cos"; + case EOpTan: return "tan"; + case EOpAsin: return "asin"; + case EOpAcos: return "acos"; + case EOpAtan: return "atan"; + case EOpExp: return "exp"; + case EOpLog: return "log"; + case EOpExp2: return "exp2"; + case EOpLog2: return "log2"; + case EOpSqrt: return "sqrt"; + case EOpInverseSqrt: return "inversesqrt"; + case EOpAbs: return "abs"; + case EOpSign: return "sign"; + case EOpFloor: return "floor"; + case EOpCeil: return "ceil"; + case EOpFract: return "fract"; + case EOpLength: return "length"; + case EOpNormalize: return "normalize"; + case EOpDFdx: return "dFdx"; + case EOpDFdy: return "dFdy"; + case EOpFwidth: return "fwidth"; + case EOpAny: return "any"; + case EOpAll: return "all"; + + default: break; + } + return ""; +} + +//////////////////////////////////////////////////////////////////////////// +// +// First set of functions are to help build the intermediate representation. +// These functions are not member functions of the nodes. +// They are called from parser productions. +// +///////////////////////////////////////////////////////////////////////////// + +// +// Add a terminal node for an identifier in an expression. +// +// Returns the added node. +// +TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line) +{ + TIntermSymbol* node = new TIntermSymbol(id, name, type); + node->setLine(line); + + return node; +} + +// +// Connect two nodes with a new parent that does a binary operation on the nodes. +// +// Returns the added node. +// +TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable) +{ + switch (op) { + case EOpEqual: + case EOpNotEqual: + if (left->isArray()) + return 0; + break; + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) { + return 0; + } + break; + case EOpLogicalOr: + case EOpLogicalXor: + case EOpLogicalAnd: + if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) { + return 0; + } + break; + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpMul: + if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) + return 0; + default: break; + } + + // + // First try converting the children to compatible types. + // + if (left->getType().getStruct() && right->getType().getStruct()) { + if (left->getType() != right->getType()) + return 0; + } else { + TIntermTyped* child = addConversion(op, left->getType(), right); + if (child) + right = child; + else { + child = addConversion(op, right->getType(), left); + if (child) + left = child; + else + return 0; + } + } + + // + // Need a new node holding things together then. Make + // one and promote it to the right type. + // + TIntermBinary* node = new TIntermBinary(op); + if (line == 0) + line = right->getLine(); + node->setLine(line); + + node->setLeft(left); + node->setRight(right); + if (!node->promote(infoSink)) + return 0; + + // + // See if we can fold constants. + // + TIntermTyped* typedReturnNode = 0; + TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion(); + TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion(); + if (leftTempConstant && rightTempConstant) { + typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink); + + if (typedReturnNode) + return typedReturnNode; + } + + return node; +} + +// +// Connect two nodes through an assignment. +// +// Returns the added node. +// +TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line) +{ + // + // Like adding binary math, except the conversion can only go + // from right to left. + // + TIntermBinary* node = new TIntermBinary(op); + if (line == 0) + line = left->getLine(); + node->setLine(line); + + TIntermTyped* child = addConversion(op, left->getType(), right); + if (child == 0) + return 0; + + node->setLeft(left); + node->setRight(child); + if (! node->promote(infoSink)) + return 0; + + return node; +} + +// +// Connect two nodes through an index operator, where the left node is the base +// of an array or struct, and the right node is a direct or indirect offset. +// +// Returns the added node. +// The caller should set the type of the returned node. +// +TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line) +{ + TIntermBinary* node = new TIntermBinary(op); + if (line == 0) + line = index->getLine(); + node->setLine(line); + node->setLeft(base); + node->setRight(index); + + // caller should set the type + + return node; +} + +// +// Add one node as the parent of another that it operates on. +// +// Returns the added node. +// +TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable) +{ + TIntermUnary* node; + TIntermTyped* child = childNode->getAsTyped(); + + if (child == 0) { + infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line); + return 0; + } + + switch (op) { + case EOpLogicalNot: + if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) { + return 0; + } + break; + + case EOpPostIncrement: + case EOpPreIncrement: + case EOpPostDecrement: + case EOpPreDecrement: + case EOpNegative: + if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) + return 0; + default: break; + } + + // + // Do we need to promote the operand? + // + // Note: Implicit promotions were removed from the language. + // + TBasicType newType = EbtVoid; + switch (op) { + case EOpConstructInt: newType = EbtInt; break; + case EOpConstructBool: newType = EbtBool; break; + case EOpConstructFloat: newType = EbtFloat; break; + default: break; + } + + if (newType != EbtVoid) { + child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary, + child->getNominalSize(), + child->isMatrix(), + child->isArray()), + child); + if (child == 0) + return 0; + } + + // + // For constructors, we are now done, it's all in the conversion. + // + switch (op) { + case EOpConstructInt: + case EOpConstructBool: + case EOpConstructFloat: + return child; + default: break; + } + + TIntermConstantUnion *childTempConstant = 0; + if (child->getAsConstantUnion()) + childTempConstant = child->getAsConstantUnion(); + + // + // Make a new node for the operator. + // + node = new TIntermUnary(op); + if (line == 0) + line = child->getLine(); + node->setLine(line); + node->setOperand(child); + + if (! node->promote(infoSink)) + return 0; + + if (childTempConstant) { + TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink); + + if (newChild) + return newChild; + } + + return node; +} + +// +// This is the safe way to change the operator on an aggregate, as it +// does lots of error checking and fixing. Especially for establishing +// a function call's operation on it's set of parameters. Sequences +// of instructions are also aggregates, but they just direnctly set +// their operator to EOpSequence. +// +// Returns an aggregate node, which could be the one passed in if +// it was already an aggregate. +// +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(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, TSourceLoc line) +{ + TIntermNode* node = new TIntermLoop(type, init, cond, expr, body); + node->setLine(line); + + return node; +} + +// +// Add branches. +// +TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line) +{ + return addBranch(branchOp, 0, line); +} + +TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line) +{ + TIntermBranch* node = new TIntermBranch(branchOp, expression); + node->setLine(line); + + return node; +} + +// +// This is to be executed once the final root is put on top by the parsing +// process. +// +bool TIntermediate::postProcess(TIntermNode* root) +{ + if (root == 0) + return true; + + // + // First, finish off the top level sequence, if any + // + TIntermAggregate* aggRoot = root->getAsAggregate(); + if (aggRoot && aggRoot->getOp() == EOpNull) + aggRoot->setOp(EOpSequence); + + return true; +} + +// +// This deletes the tree. +// +void TIntermediate::remove(TIntermNode* root) +{ + if (root) + RemoveAllTreeNodes(root); +} + +//////////////////////////////////////////////////////////////// +// +// Member functions of the nodes used for building the tree. +// +//////////////////////////////////////////////////////////////// + +// +// Say whether or not an operation node changes the value of a variable. +// +// Returns true if state is modified. +// +bool TIntermOperator::modifiesState() const +{ + switch (op) { + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + case EOpAssign: + case EOpAddAssign: + case EOpSubAssign: + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + case EOpDivAssign: + return true; + default: + return false; + } +} + +// +// returns true if the operator is for one of the constructors +// +bool TIntermOperator::isConstructor() const +{ + switch (op) { + case EOpConstructVec2: + case EOpConstructVec3: + case EOpConstructVec4: + case EOpConstructMat2: + case EOpConstructMat3: + case EOpConstructMat4: + case EOpConstructFloat: + case EOpConstructIVec2: + case EOpConstructIVec3: + case EOpConstructIVec4: + case EOpConstructInt: + case EOpConstructBVec2: + case EOpConstructBVec3: + case EOpConstructBVec4: + case EOpConstructBool: + case EOpConstructStruct: + return true; + default: + return false; + } +} +// +// Make sure the type of a unary operator is appropriate for its +// combination of operation and operand type. +// +// Returns false in nothing makes sense. +// +bool TIntermUnary::promote(TInfoSink&) +{ + switch (op) { + case EOpLogicalNot: + if (operand->getBasicType() != EbtBool) + return false; + break; + case EOpNegative: + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + if (operand->getBasicType() == EbtBool) + return false; + break; + + // operators for built-ins are already type checked against their prototype + case EOpAny: + case EOpAll: + case EOpVectorLogicalNot: + return true; + + default: + if (operand->getBasicType() != EbtFloat) + return false; + } + + setType(operand->getType()); + + return true; +} + +// +// Establishes the type of the resultant operation, as well as +// makes the operator the correct one for the operands. +// +// Returns false if operator can't work on operands. +// +bool TIntermBinary::promote(TInfoSink& infoSink) +{ + // This function only handles scalars, vectors, and matrices. + if (left->isArray() || right->isArray()) { + infoSink.info.message(EPrefixInternalError, "Invalid operation for arrays", getLine()); + return false; + } + + // GLSL ES 2.0 does not support implicit type casting. + // So the basic type should always match. + if (left->getBasicType() != right->getBasicType()) + return false; + + // + // Base assumption: just make the type the same as the left + // operand. Then only deviations from this need be coded. + // + setType(left->getType()); + + // The result gets promoted to the highest precision. + TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision()); + getTypePointer()->setPrecision(higherPrecision); + + // Binary operations results in temporary variables unless both + // operands are const. + if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) { + getTypePointer()->setQualifier(EvqTemporary); + } + + int size = std::max(left->getNominalSize(), right->getNominalSize()); + + // + // All scalars. Code after this test assumes this case is removed! + // + if (size == 1) { + switch (op) { + // + // Promote to conditional + // + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + setType(TType(EbtBool, EbpUndefined)); + break; + + // + // And and Or operate on conditionals + // + case EOpLogicalAnd: + case EOpLogicalOr: + // Both operands must be of type bool. + if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool) + return false; + setType(TType(EbtBool, EbpUndefined)); + break; + + default: + break; + } + return true; + } + + // If we reach here, at least one of the operands is vector or matrix. + // The other operand could be a scalar, vector, or matrix. + // Are the sizes compatible? + // + if (left->getNominalSize() != right->getNominalSize()) { + // If the nominal size of operands do not match: + // One of them must be scalar. + if (left->getNominalSize() != 1 && right->getNominalSize() != 1) + return false; + // Operator cannot be of type pure assignment. + if (op == EOpAssign || op == EOpInitialize) + return false; + } + + // + // Can these two operands be combined? + // + TBasicType basicType = left->getBasicType(); + switch (op) { + case EOpMul: + if (!left->isMatrix() && right->isMatrix()) { + if (left->isVector()) + op = EOpVectorTimesMatrix; + else { + op = EOpMatrixTimesScalar; + setType(TType(basicType, higherPrecision, EvqTemporary, size, true)); + } + } else if (left->isMatrix() && !right->isMatrix()) { + if (right->isVector()) { + op = EOpMatrixTimesVector; + setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); + } else { + op = EOpMatrixTimesScalar; + } + } else if (left->isMatrix() && right->isMatrix()) { + op = EOpMatrixTimesMatrix; + } else if (!left->isMatrix() && !right->isMatrix()) { + if (left->isVector() && right->isVector()) { + // leave as component product + } else if (left->isVector() || right->isVector()) { + op = EOpVectorTimesScalar; + setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); + } + } else { + infoSink.info.message(EPrefixInternalError, "Missing elses", getLine()); + return false; + } + break; + case EOpMulAssign: + if (!left->isMatrix() && right->isMatrix()) { + if (left->isVector()) + op = EOpVectorTimesMatrixAssign; + else { + return false; + } + } else if (left->isMatrix() && !right->isMatrix()) { + if (right->isVector()) { + return false; + } else { + op = EOpMatrixTimesScalarAssign; + } + } else if (left->isMatrix() && right->isMatrix()) { + op = EOpMatrixTimesMatrixAssign; + } else if (!left->isMatrix() && !right->isMatrix()) { + if (left->isVector() && right->isVector()) { + // leave as component product + } else if (left->isVector() || right->isVector()) { + if (! left->isVector()) + return false; + op = EOpVectorTimesScalarAssign; + setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); + } + } else { + infoSink.info.message(EPrefixInternalError, "Missing elses", getLine()); + return false; + } + break; + + case EOpAssign: + case EOpInitialize: + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpAddAssign: + case EOpSubAssign: + case EOpDivAssign: + if ((left->isMatrix() && right->isVector()) || + (left->isVector() && right->isMatrix())) + return false; + setType(TType(basicType, higherPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix())); + break; + + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + if ((left->isMatrix() && right->isVector()) || + (left->isVector() && right->isMatrix())) + return false; + setType(TType(EbtBool, EbpUndefined)); + break; + + default: + return false; + } + + return true; +} + +bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) +{ + const TTypeList* fields = leftNodeType.getStruct(); + + size_t structSize = fields->size(); + int index = 0; + + for (size_t j = 0; j < structSize; j++) { + int size = (*fields)[j].type->getObjectSize(); + for (int i = 0; i < size; i++) { + if ((*fields)[j].type->getBasicType() == EbtStruct) { + if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index])) + return false; + } else { + if (leftUnionArray[index] != rightUnionArray[index]) + return false; + index++; + } + + } + } + return true; +} + +bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) +{ + if (leftNodeType.isArray()) { + TType typeWithoutArrayness = leftNodeType; + typeWithoutArrayness.clearArrayness(); + + int arraySize = leftNodeType.getArraySize(); + + for (int i = 0; i < arraySize; ++i) { + int offset = typeWithoutArrayness.getObjectSize() * i; + if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset])) + return false; + } + } else + return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray); + + return true; +} + +// +// The fold functions see if an operation on a constant can be done in place, +// without generating run-time code. +// +// Returns the node to keep using, which may or may not be the node passed in. +// + +TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink) +{ + ConstantUnion *unionArray = getUnionArrayPointer(); + int objectSize = getType().getObjectSize(); + + if (constantNode) { // binary operations + TIntermConstantUnion *node = constantNode->getAsConstantUnion(); + ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); + TType returnType = getType(); + + // for a case like float f = 1.2 + vec4(2,3,4,5); + if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) { + rightUnionArray = new ConstantUnion[objectSize]; + for (int i = 0; i < objectSize; ++i) + rightUnionArray[i] = *node->getUnionArrayPointer(); + returnType = getType(); + } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) { + // for a case like float f = vec4(2,3,4,5) + 1.2; + unionArray = new ConstantUnion[constantNode->getType().getObjectSize()]; + for (int i = 0; i < constantNode->getType().getObjectSize(); ++i) + unionArray[i] = *getUnionArrayPointer(); + returnType = node->getType(); + objectSize = constantNode->getType().getObjectSize(); + } + + ConstantUnion* tempConstArray = 0; + TIntermConstantUnion *tempNode; + + bool boolNodeFlag = false; + switch(op) { + case EOpAdd: + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] + rightUnionArray[i]; + } + break; + case EOpSub: + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] - rightUnionArray[i]; + } + break; + + case EOpMul: + case EOpVectorTimesScalar: + case EOpMatrixTimesScalar: + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] * rightUnionArray[i]; + } + break; + case EOpMatrixTimesMatrix: + if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) { + infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine()); + return 0; + } + {// support MSVC++6.0 + int size = getNominalSize(); + tempConstArray = new ConstantUnion[size*size]; + for (int row = 0; row < size; row++) { + for (int column = 0; column < size; column++) { + tempConstArray[size * column + row].setFConst(0.0f); + for (int i = 0; i < size; i++) { + tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst())); + } + } + } + } + break; + case EOpDiv: + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) { + switch (getType().getBasicType()) { + case EbtFloat: + if (rightUnionArray[i] == 0.0f) { + infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine()); + tempConstArray[i].setFConst(FLT_MAX); + } else + tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst()); + break; + + case EbtInt: + if (rightUnionArray[i] == 0) { + infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine()); + tempConstArray[i].setIConst(INT_MAX); + } else + tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst()); + break; + default: + infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine()); + return 0; + } + } + } + break; + + case EOpMatrixTimesVector: + if (node->getBasicType() != EbtFloat) { + infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine()); + return 0; + } + tempConstArray = new ConstantUnion[getNominalSize()]; + + {// support MSVC++6.0 + for (int size = getNominalSize(), i = 0; i < size; i++) { + tempConstArray[i].setFConst(0.0f); + for (int j = 0; j < size; j++) { + tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst())); + } + } + } + + tempNode = new TIntermConstantUnion(tempConstArray, node->getType()); + tempNode->setLine(getLine()); + + return tempNode; + + case EOpVectorTimesMatrix: + if (getType().getBasicType() != EbtFloat) { + infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine()); + return 0; + } + + tempConstArray = new ConstantUnion[getNominalSize()]; + {// support MSVC++6.0 + for (int size = getNominalSize(), i = 0; i < size; i++) { + tempConstArray[i].setFConst(0.0f); + for (int j = 0; j < size; j++) { + tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst())); + } + } + } + break; + + case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] && rightUnionArray[i]; + } + break; + + case EOpLogicalOr: // this code is written for possible future use, will not get executed currently + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] || rightUnionArray[i]; + } + break; + + case EOpLogicalXor: + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + switch (getType().getBasicType()) { + case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break; + default: assert(false && "Default missing"); + } + } + break; + + case EOpLessThan: + assert(objectSize == 1); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(*unionArray < *rightUnionArray); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + case EOpGreaterThan: + assert(objectSize == 1); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(*unionArray > *rightUnionArray); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + case EOpLessThanEqual: + { + assert(objectSize == 1); + ConstantUnion constant; + constant.setBConst(*unionArray > *rightUnionArray); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(!constant.getBConst()); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + } + case EOpGreaterThanEqual: + { + assert(objectSize == 1); + ConstantUnion constant; + constant.setBConst(*unionArray < *rightUnionArray); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(!constant.getBConst()); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + } + + case EOpEqual: + if (getType().getBasicType() == EbtStruct) { + if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) + boolNodeFlag = true; + } else { + for (int i = 0; i < objectSize; i++) { + if (unionArray[i] != rightUnionArray[i]) { + boolNodeFlag = true; + break; // break out of for loop + } + } + } + + tempConstArray = new ConstantUnion[1]; + if (!boolNodeFlag) { + tempConstArray->setBConst(true); + } + else { + tempConstArray->setBConst(false); + } + + tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); + tempNode->setLine(getLine()); + + return tempNode; + + case EOpNotEqual: + if (getType().getBasicType() == EbtStruct) { + if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) + boolNodeFlag = true; + } else { + for (int i = 0; i < objectSize; i++) { + if (unionArray[i] == rightUnionArray[i]) { + boolNodeFlag = true; + break; // break out of for loop + } + } + } + + tempConstArray = new ConstantUnion[1]; + if (!boolNodeFlag) { + tempConstArray->setBConst(true); + } + else { + tempConstArray->setBConst(false); + } + + tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); + tempNode->setLine(getLine()); + + return tempNode; + + default: + infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine()); + return 0; + } + tempNode = new TIntermConstantUnion(tempConstArray, returnType); + tempNode->setLine(getLine()); + + return tempNode; + } else { + // + // Do unary operations + // + TIntermConstantUnion *newNode = 0; + ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; + for (int i = 0; i < objectSize; i++) { + switch(op) { + case EOpNegative: + switch (getType().getBasicType()) { + case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break; + case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break; + default: + infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine()); + return 0; + } + break; + case EOpLogicalNot: // this code is written for possible future use, will not get executed currently + switch (getType().getBasicType()) { + case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break; + default: + infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine()); + return 0; + } + break; + default: + return 0; + } + } + newNode = new TIntermConstantUnion(tempConstArray, getType()); + newNode->setLine(getLine()); + return newNode; + } + + 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 000000000..a30867151 --- /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/MapLongVariableNames.cpp b/Source/ThirdParty/ANGLE/src/compiler/MapLongVariableNames.cpp new file mode 100644 index 000000000..c9b6a12b2 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/MapLongVariableNames.cpp @@ -0,0 +1,98 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/MapLongVariableNames.h" + +namespace { + +TString mapLongName(int id, const TString& name, bool isVarying) +{ + ASSERT(name.size() > MAX_IDENTIFIER_NAME_SIZE); + TStringStream stream; + stream << "webgl_"; + if (isVarying) + stream << "v"; + stream << id << "_"; + stream << name.substr(0, MAX_IDENTIFIER_NAME_SIZE - stream.str().size()); + return stream.str(); +} + +} // anonymous namespace + +MapLongVariableNames::MapLongVariableNames( + TMap<TString, TString>& varyingLongNameMap) + : mVaryingLongNameMap(varyingLongNameMap) +{ +} + +void MapLongVariableNames::visitSymbol(TIntermSymbol* symbol) +{ + ASSERT(symbol != NULL); + if (symbol->getSymbol().size() > MAX_IDENTIFIER_NAME_SIZE) { + switch (symbol->getQualifier()) { + case EvqVaryingIn: + case EvqVaryingOut: + case EvqInvariantVaryingIn: + case EvqInvariantVaryingOut: + symbol->setSymbol( + mapVaryingLongName(symbol->getSymbol())); + break; + default: + symbol->setSymbol( + mapLongName(symbol->getId(), symbol->getSymbol(), false)); + break; + }; + } +} + +void MapLongVariableNames::visitConstantUnion(TIntermConstantUnion*) +{ +} + +bool MapLongVariableNames::visitBinary(Visit, TIntermBinary*) +{ + return true; +} + +bool MapLongVariableNames::visitUnary(Visit, TIntermUnary*) +{ + return true; +} + +bool MapLongVariableNames::visitSelection(Visit, TIntermSelection*) +{ + return true; +} + +bool MapLongVariableNames::visitAggregate(Visit, TIntermAggregate*) +{ + return true; +} + +bool MapLongVariableNames::visitLoop(Visit, TIntermLoop* node) +{ + if (node->getInit()) + node->getInit()->traverse(this); + return true; +} + +bool MapLongVariableNames::visitBranch(Visit, TIntermBranch*) +{ + return true; +} + +TString MapLongVariableNames::mapVaryingLongName(const TString& name) +{ + TMap<TString, TString>::const_iterator it = mVaryingLongNameMap.find(name); + if (it != mVaryingLongNameMap.end()) + return (*it).second; + + int id = mVaryingLongNameMap.size(); + TString mappedName = mapLongName(id, name, true); + mVaryingLongNameMap.insert( + TMap<TString, TString>::value_type(name, mappedName)); + return mappedName; +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/MapLongVariableNames.h b/Source/ThirdParty/ANGLE/src/compiler/MapLongVariableNames.h new file mode 100644 index 000000000..540909ea9 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/MapLongVariableNames.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_MAP_LONG_VARIABLE_NAMES_H_ +#define COMPILER_MAP_LONG_VARIABLE_NAMES_H_ + +#include "GLSLANG/ShaderLang.h" + +#include "compiler/intermediate.h" +#include "compiler/VariableInfo.h" + +// This size does not include '\0' in the end. +#define MAX_IDENTIFIER_NAME_SIZE 32 + +// Traverses intermediate tree to map attributes and uniforms names that are +// longer than MAX_IDENTIFIER_NAME_SIZE to MAX_IDENTIFIER_NAME_SIZE. +class MapLongVariableNames : public TIntermTraverser { +public: + MapLongVariableNames(TMap<TString, TString>& varyingLongNameMap); + + virtual void visitSymbol(TIntermSymbol*); + virtual void visitConstantUnion(TIntermConstantUnion*); + virtual bool visitBinary(Visit, TIntermBinary*); + virtual bool visitUnary(Visit, TIntermUnary*); + virtual bool visitSelection(Visit, TIntermSelection*); + virtual bool visitAggregate(Visit, TIntermAggregate*); + virtual bool visitLoop(Visit, TIntermLoop*); + virtual bool visitBranch(Visit, TIntermBranch*); + +private: + TString mapVaryingLongName(const TString& name); + + TMap<TString, TString>& mVaryingLongNameMap; +}; + +#endif // COMPILER_MAP_LONG_VARIABLE_NAMES_H_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/OutputESSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/OutputESSL.cpp new file mode 100644 index 000000000..64ee92d44 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/OutputESSL.cpp @@ -0,0 +1,22 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/OutputESSL.h" + +TOutputESSL::TOutputESSL(TInfoSinkBase& objSink) + : TOutputGLSLBase(objSink) +{ +} + +bool TOutputESSL::writeVariablePrecision(TPrecision precision) +{ + if (precision == EbpUndefined) + return false; + + TInfoSinkBase& out = objSink(); + out << getPrecisionString(precision); + return true; +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/OutputESSL.h b/Source/ThirdParty/ANGLE/src/compiler/OutputESSL.h new file mode 100644 index 000000000..4fa73c804 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/OutputESSL.h @@ -0,0 +1,21 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef CROSSCOMPILERGLSL_OUTPUTESSL_H_ +#define CROSSCOMPILERGLSL_OUTPUTESSL_H_ + +#include "compiler/OutputGLSLBase.h" + +class TOutputESSL : public TOutputGLSLBase +{ +public: + TOutputESSL(TInfoSinkBase& objSink); + +protected: + virtual bool writeVariablePrecision(TPrecision precision); +}; + +#endif // CROSSCOMPILERGLSL_OUTPUTESSL_H_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.cpp new file mode 100644 index 000000000..dd31b4b58 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.cpp @@ -0,0 +1,17 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/OutputGLSL.h" + +TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink) + : TOutputGLSLBase(objSink) +{ +} + +bool TOutputGLSL::writeVariablePrecision(TPrecision) +{ + return false; +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.h b/Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.h new file mode 100644 index 000000000..0fe2356eb --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.h @@ -0,0 +1,21 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef CROSSCOMPILERGLSL_OUTPUTGLSL_H_ +#define CROSSCOMPILERGLSL_OUTPUTGLSL_H_ + +#include "compiler/OutputGLSLBase.h" + +class TOutputGLSL : public TOutputGLSLBase +{ +public: + TOutputGLSL(TInfoSinkBase& objSink); + +protected: + virtual bool writeVariablePrecision(TPrecision); +}; + +#endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/OutputGLSLBase.cpp b/Source/ThirdParty/ANGLE/src/compiler/OutputGLSLBase.cpp new file mode 100644 index 000000000..a0feb07eb --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/OutputGLSLBase.cpp @@ -0,0 +1,707 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/OutputGLSLBase.h" +#include "compiler/debug.h" + +namespace +{ +TString getTypeName(const TType& type) +{ + TInfoSinkBase out; + if (type.isMatrix()) + { + out << "mat"; + out << type.getNominalSize(); + } + else if (type.isVector()) + { + switch (type.getBasicType()) + { + case EbtFloat: out << "vec"; break; + case EbtInt: out << "ivec"; break; + case EbtBool: out << "bvec"; break; + default: UNREACHABLE(); break; + } + out << type.getNominalSize(); + } + else + { + if (type.getBasicType() == EbtStruct) + out << type.getTypeName(); + else + out << type.getBasicString(); + } + return TString(out.c_str()); +} + +TString arrayBrackets(const TType& type) +{ + ASSERT(type.isArray()); + TInfoSinkBase out; + out << "[" << type.getArraySize() << "]"; + return TString(out.c_str()); +} + +bool isSingleStatement(TIntermNode* node) { + if (const TIntermAggregate* aggregate = node->getAsAggregate()) + { + return (aggregate->getOp() != EOpFunction) && + (aggregate->getOp() != EOpSequence); + } + else if (const TIntermSelection* selection = node->getAsSelectionNode()) + { + // Ternary operators are usually part of an assignment operator. + // This handles those rare cases in which they are all by themselves. + return selection->usesTernaryOperator(); + } + else if (node->getAsLoopNode()) + { + return false; + } + return true; +} +} // namespace + +TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink) + : TIntermTraverser(true, true, true), + mObjSink(objSink), + mDeclaringVariables(false) +{ +} + +void TOutputGLSLBase::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr) +{ + TInfoSinkBase& out = objSink(); + if (visit == PreVisit && preStr) + { + out << preStr; + } + else if (visit == InVisit && inStr) + { + out << inStr; + } + else if (visit == PostVisit && postStr) + { + out << postStr; + } +} + +void TOutputGLSLBase::writeVariableType(const TType& type) +{ + TInfoSinkBase& out = objSink(); + TQualifier qualifier = type.getQualifier(); + // TODO(alokp): Validate qualifier for variable declarations. + if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal)) + out << type.getQualifierString() << " "; + // Declare the struct if we have not done so already. + if ((type.getBasicType() == EbtStruct) && + (mDeclaredStructs.find(type.getTypeName()) == mDeclaredStructs.end())) + { + out << "struct " << type.getTypeName() << "{\n"; + const TTypeList* structure = type.getStruct(); + ASSERT(structure != NULL); + for (size_t i = 0; i < structure->size(); ++i) + { + const TType* fieldType = (*structure)[i].type; + ASSERT(fieldType != NULL); + if (writeVariablePrecision(fieldType->getPrecision())) + out << " "; + out << getTypeName(*fieldType) << " " << fieldType->getFieldName(); + if (fieldType->isArray()) + out << arrayBrackets(*fieldType); + out << ";\n"; + } + out << "}"; + mDeclaredStructs.insert(type.getTypeName()); + } + else + { + if (writeVariablePrecision(type.getPrecision())) + out << " "; + out << getTypeName(type); + } +} + +void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence& args) +{ + TInfoSinkBase& out = objSink(); + for (TIntermSequence::const_iterator iter = args.begin(); + iter != args.end(); ++iter) + { + const TIntermSymbol* arg = (*iter)->getAsSymbolNode(); + ASSERT(arg != NULL); + + const TType& type = arg->getType(); + writeVariableType(type); + + const TString& name = arg->getSymbol(); + if (!name.empty()) + out << " " << name; + if (type.isArray()) + out << arrayBrackets(type); + + // Put a comma if this is not the last argument. + if (iter != args.end() - 1) + out << ", "; + } +} + +const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type, + const ConstantUnion* pConstUnion) +{ + TInfoSinkBase& out = objSink(); + + if (type.getBasicType() == EbtStruct) + { + out << type.getTypeName() << "("; + const TTypeList* structure = type.getStruct(); + ASSERT(structure != NULL); + for (size_t i = 0; i < structure->size(); ++i) + { + const TType* fieldType = (*structure)[i].type; + ASSERT(fieldType != NULL); + pConstUnion = writeConstantUnion(*fieldType, pConstUnion); + if (i != structure->size() - 1) out << ", "; + } + out << ")"; + } + else + { + int size = type.getObjectSize(); + bool writeType = size > 1; + if (writeType) out << getTypeName(type) << "("; + for (int i = 0; i < size; ++i, ++pConstUnion) + { + switch (pConstUnion->getType()) + { + case EbtFloat: out << pConstUnion->getFConst(); break; + case EbtInt: out << pConstUnion->getIConst(); break; + case EbtBool: out << pConstUnion->getBConst(); break; + default: UNREACHABLE(); + } + if (i != size - 1) out << ", "; + } + if (writeType) out << ")"; + } + return pConstUnion; +} + +void TOutputGLSLBase::visitSymbol(TIntermSymbol* node) +{ + TInfoSinkBase& out = objSink(); + if (mLoopUnroll.NeedsToReplaceSymbolWithValue(node)) + out << mLoopUnroll.GetLoopIndexValue(node); + else + out << node->getSymbol(); + + if (mDeclaringVariables && node->getType().isArray()) + out << arrayBrackets(node->getType()); +} + +void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion* node) +{ + writeConstantUnion(node->getType(), node->getUnionArrayPointer()); +} + +bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node) +{ + bool visitChildren = true; + TInfoSinkBase& out = objSink(); + switch (node->getOp()) + { + case EOpInitialize: + if (visit == InVisit) + { + out << " = "; + // RHS of initialize is not being declared. + mDeclaringVariables = false; + } + break; + case EOpAssign: writeTriplet(visit, "(", " = ", ")"); break; + case EOpAddAssign: writeTriplet(visit, "(", " += ", ")"); break; + case EOpSubAssign: writeTriplet(visit, "(", " -= ", ")"); break; + case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break; + // Notice the fall-through. + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + writeTriplet(visit, "(", " *= ", ")"); + break; + + case EOpIndexDirect: + case EOpIndexIndirect: + writeTriplet(visit, NULL, "[", "]"); + break; + case EOpIndexDirectStruct: + if (visit == InVisit) + { + out << "."; + // TODO(alokp): ASSERT + out << node->getType().getFieldName(); + visitChildren = false; + } + break; + case EOpVectorSwizzle: + if (visit == InVisit) + { + out << "."; + TIntermAggregate* rightChild = node->getRight()->getAsAggregate(); + TIntermSequence& sequence = rightChild->getSequence(); + for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit) + { + TIntermConstantUnion* element = (*sit)->getAsConstantUnion(); + ASSERT(element->getBasicType() == EbtInt); + ASSERT(element->getNominalSize() == 1); + const ConstantUnion& data = element->getUnionArrayPointer()[0]; + ASSERT(data.getType() == EbtInt); + switch (data.getIConst()) + { + case 0: out << "x"; break; + case 1: out << "y"; break; + case 2: out << "z"; break; + case 3: out << "w"; break; + default: UNREACHABLE(); break; + } + } + visitChildren = false; + } + break; + + case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break; + case EOpSub: writeTriplet(visit, "(", " - ", ")"); break; + case EOpMul: writeTriplet(visit, "(", " * ", ")"); break; + case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break; + case EOpMod: UNIMPLEMENTED(); break; + case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break; + case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break; + case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break; + case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break; + case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break; + case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break; + + // Notice the fall-through. + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpMatrixTimesMatrix: + writeTriplet(visit, "(", " * ", ")"); + break; + + case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break; + case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break; + case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break; + default: UNREACHABLE(); break; + } + + return visitChildren; +} + +bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node) +{ + 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 EOpDFdx: writeTriplet(visit, "dFdx(", NULL, ")"); break; + case EOpDFdy: writeTriplet(visit, "dFdy(", NULL, ")"); break; + case EOpFwidth: writeTriplet(visit, "fwidth(", NULL, ")"); break; + + case EOpAny: writeTriplet(visit, "any(", NULL, ")"); break; + case EOpAll: writeTriplet(visit, "all(", NULL, ")"); break; + + default: UNREACHABLE(); break; + } + + return true; +} + +bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection* node) +{ + TInfoSinkBase& out = objSink(); + + if (node->usesTernaryOperator()) + { + // Notice two brackets at the beginning and end. The outer ones + // encapsulate the whole ternary expression. This preserves the + // order of precedence when ternary expressions are used in a + // compound expression, i.e., c = 2 * (a < b ? 1 : 2). + out << "(("; + node->getCondition()->traverse(this); + out << ") ? ("; + node->getTrueBlock()->traverse(this); + out << ") : ("; + node->getFalseBlock()->traverse(this); + out << "))"; + } + else + { + out << "if ("; + node->getCondition()->traverse(this); + out << ")\n"; + + incrementDepth(); + visitCodeBlock(node->getTrueBlock()); + + if (node->getFalseBlock()) + { + out << "else\n"; + visitCodeBlock(node->getFalseBlock()); + } + decrementDepth(); + } + return false; +} + +bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) +{ + bool visitChildren = true; + TInfoSinkBase& out = objSink(); + 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); + writeVariableType(node->getType()); + out << " " << TFunction::unmangleName(node->getName()); + + incrementDepth(); + // Function definition node contains one or two children nodes + // representing function parameters and function body. The latter + // is not present in case of empty function bodies. + const TIntermSequence& sequence = node->getSequence(); + ASSERT((sequence.size() == 1) || (sequence.size() == 2)); + TIntermSequence::const_iterator seqIter = sequence.begin(); + + // Traverse function parameters. + TIntermAggregate* params = (*seqIter)->getAsAggregate(); + ASSERT(params != NULL); + ASSERT(params->getOp() == EOpParameters); + params->traverse(this); + + // Traverse function body. + TIntermAggregate* body = ++seqIter != sequence.end() ? + (*seqIter)->getAsAggregate() : NULL; + visitCodeBlock(body); + decrementDepth(); + + // Fully processed; no need to visit children. + visitChildren = false; + break; + } + case EOpFunctionCall: + // Function call. + if (visit == PreVisit) + { + TString functionName = TFunction::unmangleName(node->getName()); + out << functionName << "("; + } + else if (visit == InVisit) + { + out << ", "; + } + else + { + out << ")"; + } + break; + case EOpParameters: { + // Function parameters. + ASSERT(visit == PreVisit); + out << "("; + writeFunctionParameters(node->getSequence()); + out << ")"; + visitChildren = false; + break; + } + case EOpDeclaration: { + // Variable declaration. + if (visit == PreVisit) + { + const TIntermSequence& sequence = node->getSequence(); + const TIntermTyped* variable = sequence.front()->getAsTyped(); + writeVariableType(variable->getType()); + out << " "; + mDeclaringVariables = true; + } + else if (visit == InVisit) + { + out << ", "; + mDeclaringVariables = true; + } + else + { + mDeclaringVariables = false; + } + break; + } + case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break; + case EOpConstructVec2: writeTriplet(visit, "vec2(", ", ", ")"); break; + case EOpConstructVec3: writeTriplet(visit, "vec3(", ", ", ")"); break; + case EOpConstructVec4: writeTriplet(visit, "vec4(", ", ", ")"); break; + case EOpConstructBool: writeTriplet(visit, "bool(", NULL, ")"); break; + case EOpConstructBVec2: writeTriplet(visit, "bvec2(", ", ", ")"); break; + case EOpConstructBVec3: writeTriplet(visit, "bvec3(", ", ", ")"); break; + case EOpConstructBVec4: writeTriplet(visit, "bvec4(", ", ", ")"); break; + case EOpConstructInt: writeTriplet(visit, "int(", NULL, ")"); break; + case EOpConstructIVec2: writeTriplet(visit, "ivec2(", ", ", ")"); break; + case EOpConstructIVec3: writeTriplet(visit, "ivec3(", ", ", ")"); break; + case EOpConstructIVec4: writeTriplet(visit, "ivec4(", ", ", ")"); break; + case EOpConstructMat2: writeTriplet(visit, "mat2(", ", ", ")"); break; + case EOpConstructMat3: writeTriplet(visit, "mat3(", ", ", ")"); break; + case EOpConstructMat4: writeTriplet(visit, "mat4(", ", ", ")"); break; + case EOpConstructStruct: + if (visit == PreVisit) + { + const TType& type = node->getType(); + ASSERT(type.getBasicType() == EbtStruct); + out << type.getTypeName() << "("; + } + else if (visit == InVisit) + { + out << ", "; + } + else + { + out << ")"; + } + break; + + case EOpLessThan: 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 TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node) +{ + TInfoSinkBase& out = objSink(); + + incrementDepth(); + // Loop header. + TLoopType loopType = node->getType(); + if (loopType == ELoopFor) // for loop + { + if (!node->getUnrollFlag()) { + out << "for ("; + if (node->getInit()) + node->getInit()->traverse(this); + out << "; "; + + if (node->getCondition()) + node->getCondition()->traverse(this); + out << "; "; + + if (node->getExpression()) + node->getExpression()->traverse(this); + out << ")\n"; + } + } + else if (loopType == ELoopWhile) // while loop + { + out << "while ("; + ASSERT(node->getCondition() != NULL); + node->getCondition()->traverse(this); + out << ")\n"; + } + else // do-while loop + { + ASSERT(loopType == ELoopDoWhile); + out << "do\n"; + } + + // Loop body. + if (node->getUnrollFlag()) + { + TLoopIndexInfo indexInfo; + mLoopUnroll.FillLoopIndexInfo(node, indexInfo); + mLoopUnroll.Push(indexInfo); + while (mLoopUnroll.SatisfiesLoopCondition()) + { + visitCodeBlock(node->getBody()); + mLoopUnroll.Step(); + } + mLoopUnroll.Pop(); + } + else + { + visitCodeBlock(node->getBody()); + } + + // Loop footer. + if (loopType == ELoopDoWhile) // do-while loop + { + out << "while ("; + ASSERT(node->getCondition() != NULL); + node->getCondition()->traverse(this); + out << ");\n"; + } + decrementDepth(); + + // No need to visit children. They have been already processed in + // this function. + return false; +} + +bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch* node) +{ + switch (node->getFlowOp()) + { + case EOpKill: writeTriplet(visit, "discard", NULL, NULL); break; + case EOpBreak: writeTriplet(visit, "break", NULL, NULL); break; + case EOpContinue: writeTriplet(visit, "continue", NULL, NULL); break; + case EOpReturn: writeTriplet(visit, "return ", NULL, NULL); break; + default: UNREACHABLE(); break; + } + + return true; +} + +void TOutputGLSLBase::visitCodeBlock(TIntermNode* node) { + TInfoSinkBase &out = objSink(); + if (node != NULL) + { + node->traverse(this); + // Single statements not part of a sequence need to be terminated + // with semi-colon. + if (isSingleStatement(node)) + out << ";\n"; + } + else + { + out << "{\n}\n"; // Empty code block. + } +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/OutputGLSLBase.h b/Source/ThirdParty/ANGLE/src/compiler/OutputGLSLBase.h new file mode 100644 index 000000000..efd0b5fc2 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/OutputGLSLBase.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ +#define CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ + +#include <set> + +#include "compiler/ForLoopUnroll.h" +#include "compiler/intermediate.h" +#include "compiler/ParseHelper.h" + +class TOutputGLSLBase : public TIntermTraverser +{ +public: + TOutputGLSLBase(TInfoSinkBase& objSink); + +protected: + TInfoSinkBase& objSink() { return mObjSink; } + void writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr); + void writeVariableType(const TType& type); + virtual bool writeVariablePrecision(TPrecision precision) = 0; + void writeFunctionParameters(const TIntermSequence& args); + const ConstantUnion* writeConstantUnion(const TType& type, const ConstantUnion* pConstUnion); + + virtual void visitSymbol(TIntermSymbol* node); + virtual void visitConstantUnion(TIntermConstantUnion* node); + virtual bool visitBinary(Visit visit, TIntermBinary* node); + virtual bool visitUnary(Visit visit, TIntermUnary* node); + virtual bool visitSelection(Visit visit, TIntermSelection* node); + virtual bool visitAggregate(Visit visit, TIntermAggregate* node); + virtual bool visitLoop(Visit visit, TIntermLoop* node); + virtual bool visitBranch(Visit visit, TIntermBranch* node); + + void visitCodeBlock(TIntermNode* node); + +private: + TInfoSinkBase& mObjSink; + bool mDeclaringVariables; + + // Structs are declared as the tree is traversed. This set contains all + // the structs already declared. It is maintained so that a struct is + // declared only once. + typedef std::set<TString> DeclaredStructs; + DeclaredStructs mDeclaredStructs; + + ForLoopUnroll mLoopUnroll; +}; + +#endif // CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp new file mode 100644 index 000000000..afa8f046b --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp @@ -0,0 +1,2349 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/OutputHLSL.h" + +#include "compiler/debug.h" +#include "compiler/InfoSink.h" +#include "compiler/UnfoldSelect.h" +#include "compiler/SearchSymbol.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; + mUsesTexture2DProjLod = false; + mUsesTexture2DLod = false; + mUsesTextureCube = false; + mUsesTextureCube_bias = false; + mUsesTextureCubeLod = 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; + + mUniqueIndex = 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() +{ + ShShaderType shaderType = mContext.shaderType; + TInfoSinkBase &out = mHeader; + + for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++) + { + out << *structDeclaration; + } + + for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++) + { + out << *constructor; + } + + if (shaderType == SH_FRAGMENT_SHADER) + { + TString uniforms; + TString varyings; + + TSymbolTableLevel *symbols = mContext.symbolTable.getGlobalLevel(); + int semanticIndex = 0; + + for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++) + { + const TSymbol *symbol = (*namedSymbol).second; + const TString &name = symbol->getName(); + + if (symbol->isVariable()) + { + const TVariable *variable = static_cast<const TVariable*>(symbol); + const TType &type = variable->getType(); + TQualifier qualifier = type.getQualifier(); + + if (qualifier == EvqUniform) + { + if (mReferencedUniforms.find(name.c_str()) != mReferencedUniforms.end()) + { + uniforms += "uniform " + typeString(type) + " " + 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"; + + // The texture fetch functions "flip" the Y coordinate in one way or another. This is because textures are stored + // according to the OpenGL convention, i.e. (0, 0) is "bottom left", rather than the D3D convention where (0, 0) + // is "top left". Since the HLSL texture fetch functions expect textures to be stored according to the D3D + // convention, the Y coordinate passed to these functions is adjusted to compensate. + // + // The simplest case is texture2D where the mapping is Y -> 1-Y, which maps [0, 1] -> [1, 0]. + // + // The texture2DProj functions are more complicated because the projection divides by either Z or W. For the vec3 + // case, the mapping is Y -> Z-Y or Y/Z -> 1-Y/Z, which again maps [0, 1] -> [1, 0]. + // + // For cube textures the mapping is Y -> -Y, which maps [-1, 1] -> [1, -1]. This is not sufficient on its own for the + // +Y and -Y faces, which are now on the "wrong sides" of the cube. This is compensated for by exchanging the + // +Y and -Y faces everywhere else throughout the code. + + if (mUsesTexture2D) + { + out << "float4 gl_texture2D(sampler2D s, float2 t)\n" + "{\n" + " return tex2D(s, float2(t.x, 1 - t.y));\n" + "}\n" + "\n"; + } + + if (mUsesTexture2D_bias) + { + out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n" + "{\n" + " return tex2Dbias(s, float4(t.x, 1 - 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.z - t.y, 0, t.z));\n" + "}\n" + "\n" + "float4 gl_texture2DProj(sampler2D s, float4 t)\n" + "{\n" + " return tex2Dproj(s, float4(t.x, t.w - t.y, t.z, t.w));\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, 1 - (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, 1 - (t.y / t.w), 0, bias));\n" + "}\n" + "\n"; + } + + if (mUsesTextureCube) + { + out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" + "{\n" + " return texCUBE(s, float3(t.x, -t.y, t.z));\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"; + + // The texture fetch functions "flip" the Y coordinate in one way or another. This is because textures are stored + // according to the OpenGL convention, i.e. (0, 0) is "bottom left", rather than the D3D convention where (0, 0) + // is "top left". Since the HLSL texture fetch functions expect textures to be stored according to the D3D + // convention, the Y coordinate passed to these functions is adjusted to compensate. + // + // The simplest case is texture2D where the mapping is Y -> 1-Y, which maps [0, 1] -> [1, 0]. + // + // The texture2DProj functions are more complicated because the projection divides by either Z or W. For the vec3 + // case, the mapping is Y -> Z-Y or Y/Z -> 1-Y/Z, which again maps [0, 1] -> [1, 0]. + // + // For cube textures the mapping is Y -> -Y, which maps [-1, 1] -> [1, -1]. This is not sufficient on its own for the + // +Y and -Y faces, which are now on the "wrong sides" of the cube. This is compensated for by exchanging the + // +Y and -Y faces everywhere else throughout the code. + + if (mUsesTexture2D) + { + out << "float4 gl_texture2D(sampler2D s, float2 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x, 1 - t.y, 0, 0));\n" + "}\n" + "\n"; + } + + if (mUsesTexture2DLod) + { + out << "float4 gl_texture2DLod(sampler2D s, float2 t, float lod)\n" + "{\n" + " return tex2Dlod(s, float4(t.x, 1 - t.y, 0, lod));\n" + "}\n" + "\n"; + } + + if (mUsesTexture2DProj) + { + out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.z, 1 - t.y / t.z, 0, 0));\n" + "}\n" + "\n" + "float4 gl_texture2DProj(sampler2D s, float4 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.w, 1 - t.y / t.w, 0, 0));\n" + "}\n" + "\n"; + } + + if (mUsesTexture2DProjLod) + { + out << "float4 gl_texture2DProjLod(sampler2D s, float3 t, float lod)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.z, 1 - t.y / t.z, 0, lod));\n" + "}\n" + "\n" + "float4 gl_texture2DProjLod(sampler2D s, float4 t, float lod)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.w, 1 - t.y / t.w, 0, lod));\n" + "}\n" + "\n"; + } + + if (mUsesTextureCube) + { + out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" + "{\n" + " return texCUBElod(s, float4(t.x, -t.y, t.z, 0));\n" + "}\n" + "\n"; + } + + if (mUsesTextureCubeLod) + { + out << "float4 gl_textureCubeLod(samplerCUBE s, float3 t, float lod)\n" + "{\n" + " return texCUBElod(s, float4(t.x, -t.y, t.z, lod));\n" + "}\n" + "\n"; + } + } + + if (mUsesFragCoord) + { + out << "#define GL_USES_FRAG_COORD\n"; + } + + if (mUsesPointCoord) + { + out << "#define GL_USES_POINT_COORD\n"; + } + + if (mUsesFrontFacing) + { + out << "#define GL_USES_FRONT_FACING\n"; + } + + if (mUsesPointSize) + { + out << "#define GL_USES_POINT_SIZE\n"; + } + + if (mUsesDepthRange) + { + out << "struct gl_DepthRangeParameters\n" + "{\n" + " float near;\n" + " float far;\n" + " float diff;\n" + "};\n" + "\n" + "uniform float3 dx_DepthRange;" + "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" + "\n"; + } + + if (mUsesXor) + { + out << "bool xor(bool p, bool q)\n" + "{\n" + " return (p || q) && !(p && q);\n" + "}\n" + "\n"; + } + + if (mUsesMod1) + { + out << "float mod(float x, float y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"; + } + + if (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: + if (visit == PreVisit) + { + // GLSL allows to write things like "float x = x;" where a new variable x is defined + // and the value of an existing variable x is assigned. HLSL uses C semantics (the + // new variable is created before the assignment is evaluated), so we need to convert + // this to "float t = x, x = t;". + + TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode(); + TIntermTyped *expression = node->getRight(); + + sh::SearchSymbol searchSymbol(symbolNode->getSymbol()); + expression->traverse(&searchSymbol); + bool sameSymbol = searchSymbol.foundMatch(); + + if (sameSymbol) + { + // Type already printed + out << "t" + str(mUniqueIndex) + " = "; + expression->traverse(this); + out << ", "; + symbolNode->traverse(this); + out << " = t" + str(mUniqueIndex); + + mUniqueIndex++; + return false; + } + } + else if (visit == InVisit) + { + out << " = "; + } + break; + case EOpAddAssign: outputTriplet(visit, "(", " += ", ")"); break; + case EOpSubAssign: outputTriplet(visit, "(", " -= ", ")"); break; + case EOpMulAssign: outputTriplet(visit, "(", " *= ", ")"); break; + case EOpVectorTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break; + case EOpMatrixTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break; + case EOpVectorTimesMatrixAssign: + if (visit == PreVisit) + { + out << "("; + } + else if (visit == InVisit) + { + out << " = mul("; + node->getLeft()->traverse(this); + out << ", transpose("; + } + else + { + out << ")))"; + } + break; + case EOpMatrixTimesMatrixAssign: + if (visit == PreVisit) + { + out << "("; + } + else if (visit == InVisit) + { + out << " = mul("; + node->getLeft()->traverse(this); + out << ", "; + } + else + { + out << "))"; + } + break; + case EOpDivAssign: outputTriplet(visit, "(", " /= ", ")"); break; + case EOpIndexDirect: outputTriplet(visit, "", "[", "]"); break; + case EOpIndexIndirect: outputTriplet(visit, "", "[", "]"); break; + case EOpIndexDirectStruct: + if (visit == InVisit) + { + out << "." + 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 EOpDFdx: outputTriplet(visit, "ddx(", "", ")"); break; + case EOpDFdy: 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) +{ + ShShaderType shaderType = mContext.shaderType; + TInfoSinkBase &out = mBody; + + switch (node->getOp()) + { + case EOpSequence: + { + if (mInsideFunction) + { + outputLineDirective(node->getLine()); + out << "{\n"; + + mScopeDepth++; + + if (mScopeBracket.size() < mScopeDepth) + { + mScopeBracket.push_back(0); // New scope level + } + else + { + mScopeBracket[mScopeDepth - 1]++; // New scope at existing level + } + } + + for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++) + { + outputLineDirective((*sit)->getLine()); + + if (isSingleStatement(*sit)) + { + mUnfoldSelect->traverse(*sit); + } + + (*sit)->traverse(this); + + out << ";\n"; + } + + if (mInsideFunction) + { + outputLineDirective(node->getEndLine()); + out << "}\n"; + + mScopeDepth--; + } + + return false; + } + case EOpDeclaration: + if (visit == PreVisit) + { + TIntermSequence &sequence = node->getSequence(); + TIntermTyped *variable = sequence[0]->getAsTyped(); + bool visit = true; + + if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal)) + { + if (variable->getType().getStruct()) + { + addConstructor(variable->getType(), scopedStruct(variable->getType().getTypeName()), NULL); + } + + if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration + { + if (!mInsideFunction) + { + out << "static "; + } + + out << typeString(variable->getType()) + " "; + + for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) + { + TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); + + if (symbol) + { + symbol->traverse(this); + out << arrayString(symbol->getType()); + out << " = " + initializer(variable->getType()); + } + else + { + (*sit)->traverse(this); + } + + if (visit && this->inVisit) + { + if (*sit != sequence.back()) + { + visit = this->visitAggregate(InVisit, node); + } + } + } + + if (visit && this->postVisit) + { + this->visitAggregate(PostVisit, node); + } + } + else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration + { + // Already added to constructor map + } + else UNREACHABLE(); + } + + return false; + } + else if (visit == InVisit) + { + out << ", "; + } + break; + case EOpPrototype: + if (visit == PreVisit) + { + out << typeString(node->getType()) << " " << decorate(node->getName()) << "("; + + 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"; + + outputLineDirective(node->getLine()); + out << "{\n"; + + mInsideFunction = true; + } + else if (visit == PostVisit) + { + outputLineDirective(node->getEndLine()); + 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") + { + if (node->getSequence().size() == 3) + { + mUsesTexture2DLod = true; + } + else UNREACHABLE(); + + out << "gl_texture2DLod("; + } + else if (name == "texture2DProjLod") + { + if (node->getSequence().size() == 3) + { + mUsesTexture2DProjLod = true; + } + else UNREACHABLE(); + + out << "gl_texture2DProjLod("; + } + else if (name == "textureCubeLod") + { + if (node->getSequence().size() == 3) + { + mUsesTextureCubeLod = true; + } + else UNREACHABLE(); + + out << "gl_textureCubeLod("; + } + else UNREACHABLE(); + } + } + else if (visit == InVisit) + { + out << ", "; + } + else + { + out << ")"; + } + } + break; + case EOpParameters: outputTriplet(visit, "(", ", ", ")\n{\n"); break; + case EOpConstructFloat: + addConstructor(node->getType(), "vec1", &node->getSequence()); + outputTriplet(visit, "vec1(", "", ")"); + break; + case EOpConstructVec2: + addConstructor(node->getType(), "vec2", &node->getSequence()); + outputTriplet(visit, "vec2(", ", ", ")"); + break; + case EOpConstructVec3: + addConstructor(node->getType(), "vec3", &node->getSequence()); + outputTriplet(visit, "vec3(", ", ", ")"); + break; + case EOpConstructVec4: + addConstructor(node->getType(), "vec4", &node->getSequence()); + outputTriplet(visit, "vec4(", ", ", ")"); + break; + case EOpConstructBool: + addConstructor(node->getType(), "bvec1", &node->getSequence()); + outputTriplet(visit, "bvec1(", "", ")"); + break; + case EOpConstructBVec2: + addConstructor(node->getType(), "bvec2", &node->getSequence()); + outputTriplet(visit, "bvec2(", ", ", ")"); + break; + case EOpConstructBVec3: + addConstructor(node->getType(), "bvec3", &node->getSequence()); + outputTriplet(visit, "bvec3(", ", ", ")"); + break; + case EOpConstructBVec4: + addConstructor(node->getType(), "bvec4", &node->getSequence()); + outputTriplet(visit, "bvec4(", ", ", ")"); + break; + case EOpConstructInt: + addConstructor(node->getType(), "ivec1", &node->getSequence()); + outputTriplet(visit, "ivec1(", "", ")"); + break; + case EOpConstructIVec2: + addConstructor(node->getType(), "ivec2", &node->getSequence()); + outputTriplet(visit, "ivec2(", ", ", ")"); + break; + case EOpConstructIVec3: + addConstructor(node->getType(), "ivec3", &node->getSequence()); + outputTriplet(visit, "ivec3(", ", ", ")"); + break; + case EOpConstructIVec4: + addConstructor(node->getType(), "ivec4", &node->getSequence()); + outputTriplet(visit, "ivec4(", ", ", ")"); + break; + case EOpConstructMat2: + addConstructor(node->getType(), "mat2", &node->getSequence()); + outputTriplet(visit, "mat2(", ", ", ")"); + break; + case EOpConstructMat3: + addConstructor(node->getType(), "mat3", &node->getSequence()); + outputTriplet(visit, "mat3(", ", ", ")"); + break; + case EOpConstructMat4: + addConstructor(node->getType(), "mat4", &node->getSequence()); + outputTriplet(visit, "mat4(", ", ", ")"); + break; + case EOpConstructStruct: + addConstructor(node->getType(), scopedStruct(node->getType().getTypeName()), &node->getSequence()); + outputTriplet(visit, structLookup(node->getType().getTypeName()) + "_ctor(", ", ", ")"); + break; + case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; + case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break; + case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break; + case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break; + case EOpVectorEqual: outputTriplet(visit, "(", " == ", ")"); break; + case EOpVectorNotEqual: outputTriplet(visit, "(", " != ", ")"); break; + case EOpMod: + { + 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"; + + outputLineDirective(node->getLine()); + out << "{\n"; + + if (node->getTrueBlock()) + { + node->getTrueBlock()->traverse(this); + } + + outputLineDirective(node->getLine()); + out << ";}\n"; + + if (node->getFalseBlock()) + { + out << "else\n"; + + outputLineDirective(node->getFalseBlock()->getLine()); + out << "{\n"; + + outputLineDirective(node->getFalseBlock()->getLine()); + node->getFalseBlock()->traverse(this); + + outputLineDirective(node->getFalseBlock()->getLine()); + 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->getType() == ELoopDoWhile) + { + out << "do\n"; + + outputLineDirective(node->getLine()); + out << "{\n"; + } + else + { + if (node->getInit()) + { + mUnfoldSelect->traverse(node->getInit()); + } + + if (node->getCondition()) + { + mUnfoldSelect->traverse(node->getCondition()); + } + + if (node->getExpression()) + { + mUnfoldSelect->traverse(node->getExpression()); + } + + out << "for("; + + if (node->getInit()) + { + node->getInit()->traverse(this); + } + + out << "; "; + + if (node->getCondition()) + { + node->getCondition()->traverse(this); + } + + out << "; "; + + if (node->getExpression()) + { + node->getExpression()->traverse(this); + } + + out << ")\n"; + + outputLineDirective(node->getLine()); + out << "{\n"; + } + + if (node->getBody()) + { + node->getBody()->traverse(this); + } + + outputLineDirective(node->getLine()); + out << "}\n"; + + if (node->getType() == ELoopDoWhile) + { + outputLineDirective(node->getCondition()->getLine()); + out << "while(\n"; + + node->getCondition()->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;\n", "", ""); break; + case EOpBreak: outputTriplet(visit, "break;\n", "", ""); break; + case EOpContinue: outputTriplet(visit, "continue;\n", "", ""); break; + case EOpReturn: + if (visit == PreVisit) + { + if (node->getExpression()) + { + out << "return "; + } + else + { + out << "return;\n"; + } + } + else if (visit == PostVisit) + { + if (node->getExpression()) + { + out << ";\n"; + } + } + break; + default: UNREACHABLE(); + } + + return true; +} + +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->getCondition()) + { + TIntermBinary *test = node->getCondition()->getAsBinaryNode(); + + if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId()) + { + TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion(); + + if (constant) + { + if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) + { + comparator = test->getOp(); + limit = constant->getUnionArrayPointer()[0].getIConst(); + } + } + } + } + + // Parse increment + if (index != NULL && comparator != EOpNull && node->getExpression()) + { + TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode(); + TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode(); + + if (binaryTerminal) + { + TOperator op = binaryTerminal->getOp(); + TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion(); + + if (constant) + { + if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) + { + int value = constant->getUnionArrayPointer()[0].getIConst(); + + switch (op) + { + case EOpAddAssign: increment = value; break; + case EOpSubAssign: increment = -value; break; + default: UNIMPLEMENTED(); + } + } + } + } + else if (unaryTerminal) + { + TOperator op = unaryTerminal->getOp(); + + switch (op) + { + case EOpPostIncrement: increment = 1; break; + case EOpPostDecrement: increment = -1; break; + case EOpPreIncrement: increment = 1; break; + case EOpPreDecrement: increment = -1; break; + default: UNIMPLEMENTED(); + } + } + } + + if (index != NULL && comparator != EOpNull && increment != 0) + { + if (comparator == EOpLessThanEqual) + { + comparator = EOpLessThan; + limit += 1; + } + + if (comparator == EOpLessThan) + { + int iterations = (limit - initial) / increment; + + if (iterations <= 255) + { + return false; // Not an excessive loop + } + + while (iterations > 0) + { + int remainder = (limit - initial) % increment; + int clampedLimit = initial + increment * std::min(255, iterations); + + // 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"; + + outputLineDirective(node->getLine()); + out << "{\n"; + + if (node->getBody()) + { + node->getBody()->traverse(this); + } + + outputLineDirective(node->getLine()); + 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; + } +} + +void OutputHLSL::outputLineDirective(int line) +{ + if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0)) + { + mBody << "\n"; + mBody << "#line " << line; + + if (mContext.sourcePath) + { + mBody << " \"" << mContext.sourcePath << "\""; + } + + mBody << "\n"; + } +} + +TString OutputHLSL::argumentString(const TIntermSymbol *symbol) +{ + TQualifier qualifier = symbol->getQualifier(); + const TType &type = symbol->getType(); + TString name = symbol->getSymbol(); + + if (name.empty()) // HLSL demands named arguments, also for prototypes + { + name = "x" + str(mUniqueIndex++); + } + else + { + name = decorate(name); + } + + return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type); +} + +TString OutputHLSL::qualifierString(TQualifier qualifier) +{ + switch(qualifier) + { + case EvqIn: return "in"; + case EvqOut: return "out"; + case EvqInOut: return "inout"; + case EvqConstReadOnly: return "const"; + default: UNREACHABLE(); + } + + return ""; +} + +TString OutputHLSL::typeString(const TType &type) +{ + if (type.getBasicType() == EbtStruct) + { + if (type.getTypeName() != "") + { + return structLookup(type.getTypeName()); + } + else // Nameless structure, define in place + { + const TTypeList &fields = *type.getStruct(); + + TString string = "struct\n" + "{\n"; + + for (unsigned int i = 0; i < fields.size(); i++) + { + const TType &field = *fields[i].type; + + string += " " + typeString(field) + " " + 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 ¶meter = 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 ¶meter = 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 000000000..805561afb --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.h @@ -0,0 +1,131 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_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); + void outputLineDirective(int line); + TString argumentString(const TIntermSymbol *symbol); + int vectorSize(const TType &type) const; + + void addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters); + const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion); + + TString scopeString(unsigned int depthLimit); + TString scopedStruct(const TString &typeName); + TString structLookup(const TString &typeName); + + TParseContext &mContext; + 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 mUsesTexture2DLod; + bool mUsesTexture2DProj; + bool mUsesTexture2DProj_bias; + bool mUsesTexture2DProjLod; + bool mUsesTextureCube; + bool mUsesTextureCube_bias; + bool mUsesTextureCubeLod; + 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 mUniqueIndex; // For creating unique 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 000000000..3f0836d75 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/ParseHelper.cpp @@ -0,0 +1,1533 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/ParseHelper.h" + +#include <stdarg.h> +#include <stdio.h> + +#include "compiler/glslang.h" +#include "compiler/osinclude.h" +#include "compiler/InitializeParseContext.h" + +extern "C" { +extern int InitPreprocessor(); +extern int FinalizePreprocessor(); +extern void PredefineIntMacro(const char *name, int value); +} + +static void ReportInfo(TInfoSinkBase& sink, + TPrefixType type, TSourceLoc loc, + const char* reason, const char* token, + const char* extraInfo) +{ + /* VC++ format: file(linenum) : error #: 'token' : extrainfo */ + sink.prefix(type); + sink.location(loc); + sink << "'" << token << "' : " << reason << " " << extraInfo << "\n"; +} + +static void DefineExtensionMacros(const TExtensionBehavior& extBehavior) +{ + for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); + iter != extBehavior.end(); ++iter) { + PredefineIntMacro(iter->first.c_str(), 1); + } +} + +/////////////////////////////////////////////////////////////////////// +// +// 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 loc, + const char* reason, const char* token, + const char* extraInfoFormat, ...) +{ + char extraInfo[512]; + va_list marker; + va_start(marker, extraInfoFormat); + vsnprintf(extraInfo, sizeof(extraInfo), extraInfoFormat, marker); + + ReportInfo(infoSink.info, EPrefixError, loc, reason, token, extraInfo); + + va_end(marker); + ++numErrors; +} + +void TParseContext::warning(TSourceLoc loc, + const char* reason, const char* token, + const char* extraInfoFormat, ...) { + char extraInfo[512]; + va_list marker; + va_start(marker, extraInfoFormat); + vsnprintf(extraInfo, sizeof(extraInfo), extraInfoFormat, marker); + + ReportInfo(infoSink.info, EPrefixWarning, loc, reason, token, extraInfo); + + va_end(marker); +} + +// +// 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){ + if (!checksPrecisionErrors) + return false; + switch( type ){ + case EbtFloat: + if( precision == EbpUndefined ){ + error( line, "No precision specified for (float)", "", "" ); + return true; + } + break; + case EbtInt: + if( precision == EbpUndefined ){ + error( line, "No precision specified (int)", "", "" ); + return true; + } + break; + default: + return false; + } + return false; +} + +// +// Both test and if necessary, spit out an error, to see if the node is really +// an l-value that can be operated on this way. +// +// Returns true if the was an error. +// +bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* node) +{ + TIntermSymbol* symNode = node->getAsSymbolNode(); + TIntermBinary* binaryNode = node->getAsBinaryNode(); + + if (binaryNode) { + bool errorReturn; + + switch(binaryNode->getOp()) { + case EOpIndexDirect: + case EOpIndexIndirect: + case EOpIndexDirectStruct: + return lValueErrorCheck(line, op, binaryNode->getLeft()); + case EOpVectorSwizzle: + errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft()); + if (!errorReturn) { + int offset[4] = {0,0,0,0}; + + TIntermTyped* rightNode = binaryNode->getRight(); + TIntermAggregate *aggrNode = rightNode->getAsAggregate(); + + for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); + p != aggrNode->getSequence().end(); p++) { + int value = (*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getIConst(); + offset[value]++; + if (offset[value] > 1) { + error(line, " l-value of swizzle cannot have duplicate components", op, "", ""); + + return true; + } + } + } + + return errorReturn; + default: + break; + } + error(line, " l-value required", op, "", ""); + + return true; + } + + + const char* symbol = 0; + if (symNode != 0) + symbol = symNode->getSymbol().c_str(); + + const char* message = 0; + switch (node->getQualifier()) { + case EvqConst: message = "can't modify a const"; break; + case EvqConstReadOnly: message = "can't modify a const"; break; + case EvqAttribute: message = "can't modify an attribute"; break; + case EvqUniform: message = "can't modify a uniform"; break; + case EvqVaryingIn: message = "can't modify a varying"; break; + case EvqInput: message = "can't modify an input"; break; + case EvqFragCoord: message = "can't modify gl_FragCoord"; break; + case EvqFrontFacing: message = "can't modify gl_FrontFacing"; break; + case EvqPointCoord: message = "can't modify gl_PointCoord"; break; + default: + + // + // Type that can't be written to? + // + switch (node->getBasicType()) { + case EbtSampler2D: + case EbtSamplerCube: + message = "can't modify a sampler"; + break; + case EbtVoid: + message = "can't modify void"; + break; + default: + break; + } + } + + if (message == 0 && binaryNode == 0 && symNode == 0) { + error(line, " l-value required", op, "", ""); + + return true; + } + + + // + // Everything else is okay, no error. + // + if (message == 0) + return false; + + // + // If we get here, we have an error and a message. + // + if (symNode) + 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 (shaderSpec == SH_WEBGL_SPEC) { + 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) { + const TParameter& param = function.getParam(i); + size += param.type->getObjectSize(); + + if (constructingMatrix && param.type->isMatrix()) + matrixInMatrix = true; + if (full) + overFull = true; + if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize()) + full = true; + if (param.type->getQualifier() != EvqConst) + constType = false; + if (param.type->isArray()) + arrayArg = true; + } + + if (constType) + type->setQualifier(EvqConst); + + if (type->isArray() && type->getArraySize() != function.getParamCount()) { + error(line, "array constructor needs one argument per array element", "constructor", ""); + return true; + } + + if (arrayArg && op != EOpConstructStruct) { + error(line, "constructing from a non-dereferenced array", "constructor", ""); + return true; + } + + if (matrixInMatrix && !type->isArray()) { + if (function.getParamCount() != 1) { + error(line, "constructing matrix from matrix can only take one argument", "constructor", ""); + return true; + } + } + + if (overFull) { + error(line, "too many arguments", "constructor", ""); + return true; + } + + if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) { + error(line, "Number of constructor parameters does not match the number of structure fields", "constructor", ""); + return true; + } + + if (!type->isMatrix()) { + if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) || + (op == EOpConstructStruct && size < type->getObjectSize())) { + error(line, "not enough data provided for construction", "constructor", ""); + return true; + } + } + + TIntermTyped *typed = node ? node->getAsTyped() : 0; + if (typed == 0) { + error(line, "constructor argument does not have a type", "constructor", ""); + return true; + } + if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) { + error(line, "cannot convert a sampler", "constructor", ""); + return true; + } + if (typed->getBasicType() == EbtVoid) { + error(line, "cannot convert a void", "constructor", ""); + return true; + } + + return false; +} + +// This function checks to see if a void variable has been declared and raise an error message for such a case +// +// returns true in case of an error +// +bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType) +{ + if (pubType.type == EbtVoid) { + error(line, "illegal use of type 'void'", identifier.c_str(), ""); + return true; + } + + return false; +} + +// This function checks to see if the node (for the expression) contains a scalar boolean expression or not +// +// returns true in case of an error +// +bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type) +{ + if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) { + error(line, "boolean expression expected", "", ""); + return true; + } + + return false; +} + +// This function checks to see if the node (for the expression) contains a scalar boolean expression or not +// +// returns true in case of an error +// +bool TParseContext::boolErrorCheck(int line, const TPublicType& pType) +{ + if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) { + error(line, "boolean expression expected", "", ""); + return true; + } + + return false; +} + +bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason) +{ + if (pType.type == EbtStruct) { + if (containsSampler(*pType.userDef)) { + error(line, reason, getBasicString(pType.type), "(structure contains a sampler)"); + + return true; + } + + return false; + } else if (IsSampler(pType.type)) { + error(line, reason, getBasicString(pType.type), ""); + + return true; + } + + return false; +} + +bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType) +{ + if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) && + pType.type == EbtStruct) { + error(line, "cannot be used with a structure", getQualifierString(pType.qualifier), ""); + + return true; + } + + if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform")) + return true; + + return false; +} + +bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type) +{ + if ((qualifier == EvqOut || qualifier == EvqInOut) && + type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) { + error(line, "samplers cannot be output parameters", type.getBasicString(), ""); + return true; + } + + return false; +} + +bool TParseContext::containsSampler(TType& type) +{ + if (IsSampler(type.getBasicType())) + return true; + + if (type.getBasicType() == EbtStruct) { + TTypeList& structure = *type.getStruct(); + for (unsigned int i = 0; i < structure.size(); ++i) { + if (containsSampler(*structure[i].type)) + return true; + } + } + + return false; +} + +// +// Do size checking for an array type's size. +// +// Returns true if there was an error. +// +bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size) +{ + TIntermConstantUnion* constant = expr->getAsConstantUnion(); + if (constant == 0 || constant->getBasicType() != EbtInt) { + error(line, "array size must be a constant integer expression", "", ""); + return true; + } + + size = constant->getUnionArrayPointer()->getIConst(); + + if (size <= 0) { + error(line, "array size must be a positive integer", "", ""); + size = 1; + return true; + } + + return false; +} + +// +// See if this qualifier can be an array. +// +// Returns true if there is an error. +// +bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type) +{ + if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) { + error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str(), ""); + return true; + } + + return false; +} + +// +// See if this type can be an array. +// +// Returns true if there is an error. +// +bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type) +{ + // + // Can the type be an array? + // + if (type.array) { + error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str(), ""); + return true; + } + + return false; +} + +// +// Do all the semantic checking for declaring an array, with and +// without a size, and make the right changes to the symbol table. +// +// size == 0 means no specified size. +// +// Returns true if there was an error. +// +bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable) +{ + // + // Don't check for reserved word use until after we know it's not in the symbol table, + // because reserved arrays can be redeclared. + // + + bool builtIn = false; + bool sameScope = false; + TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope); + if (symbol == 0 || !sameScope) { + if (reservedErrorCheck(line, identifier)) + return true; + + variable = new TVariable(&identifier, TType(type)); + + if (type.arraySize) + variable->getType().setArraySize(type.arraySize); + + if (! symbolTable.insert(*variable)) { + delete variable; + error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str(), ""); + return true; + } + } else { + if (! symbol->isVariable()) { + error(line, "variable expected", identifier.c_str(), ""); + return true; + } + + variable = static_cast<TVariable*>(symbol); + if (! variable->getType().isArray()) { + error(line, "redeclaring non-array as array", identifier.c_str(), ""); + return true; + } + if (variable->getType().getArraySize() > 0) { + error(line, "redeclaration of array with size", identifier.c_str(), ""); + return true; + } + + if (! variable->getType().sameElementType(TType(type))) { + error(line, "redeclaration of array with a different type", identifier.c_str(), ""); + return true; + } + + TType* t = variable->getArrayInformationType(); + while (t != 0) { + if (t->getMaxArraySize() > type.arraySize) { + error(line, "higher index value already used for the array", identifier.c_str(), ""); + return true; + } + t->setArraySize(type.arraySize); + t = t->getArrayInformationType(); + } + + if (type.arraySize) + variable->getType().setArraySize(type.arraySize); + } + + if (voidErrorCheck(line, identifier, type)) + return true; + + return false; +} + +bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line) +{ + bool builtIn = false; + TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn); + if (symbol == 0) { + error(line, " undeclared identifier", node->getSymbol().c_str(), ""); + return true; + } + TVariable* variable = static_cast<TVariable*>(symbol); + + type->setArrayInformationType(variable->getArrayInformationType()); + variable->updateArrayInformationType(type); + + // special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers + // its an error + if (node->getSymbol() == "gl_FragData") { + TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", &builtIn); + 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, TVariable*& variable) +{ + if (reservedErrorCheck(line, identifier)) + recover(); + + variable = new TVariable(&identifier, TType(type)); + + if (! symbolTable.insert(*variable)) { + error(line, "redefinition", variable->getName().c_str(), ""); + delete variable; + variable = 0; + return true; + } + + if (voidErrorCheck(line, identifier, type)) + return true; + + return false; +} + +bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type) +{ + if (qualifier != EvqConst && qualifier != EvqTemporary) { + error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier), ""); + return true; + } + if (qualifier == EvqConst && paramQualifier != EvqIn) { + error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier)); + return true; + } + + if (qualifier == EvqConst) + type->setQualifier(EvqConstReadOnly); + else + type->setQualifier(paramQualifier); + + return false; +} + +bool TParseContext::extensionErrorCheck(int line, const TString& extension) +{ + TExtensionBehavior::const_iterator iter = extensionBehavior.find(extension); + if (iter == extensionBehavior.end()) { + error(line, "extension", extension.c_str(), "is not supported"); + return true; + } + if (iter->second == EBhDisable) { + error(line, "extension", extension.c_str(), "is disabled"); + return true; + } + if (iter->second == EBhWarn) { + TString msg = "extension " + extension + " is being used"; + infoSink.info.message(EPrefixWarning, msg.c_str(), line); + return false; + } + + 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) +{ + ASSERT(aggrNode != NULL); + if (!aggrNode->isConstructor()) + return false; + + bool allConstant = true; + + // check if all the child nodes are constants so that they can be inserted into + // the parent node + TIntermSequence &sequence = aggrNode->getSequence() ; + for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) { + if (!(*p)->getAsTyped()->getAsConstantUnion()) + return false; + } + + return allConstant; +} + +// This function is used to test for the correctness of the parameters passed to various constructor functions +// and also convert them to the right datatype if it is allowed and required. +// +// Returns 0 for an error or the constructed node (aggregate or typed) for no error. +// +TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line) +{ + if (node == 0) + return 0; + + TIntermAggregate* aggrNode = node->getAsAggregate(); + + TTypeList::const_iterator memberTypes; + if (op == EOpConstructStruct) + memberTypes = type->getStruct()->begin(); + + TType elementType = *type; + if (type->isArray()) + elementType.clearArrayness(); + + bool singleArg; + if (aggrNode) { + if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1) + singleArg = true; + else + singleArg = false; + } else + singleArg = true; + + TIntermTyped *newNode; + if (singleArg) { + // If structure constructor or array constructor is being called + // for only one parameter inside the structure, we need to call constructStruct function once. + if (type->isArray()) + newNode = constructStruct(node, &elementType, 1, node->getLine(), false); + else if (op == EOpConstructStruct) + newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false); + else + newNode = constructBuiltIn(type, op, node, node->getLine(), false); + + if (newNode && newNode->getAsAggregate()) { + TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type); + if (constConstructor) + return constConstructor; + } + + return newNode; + } + + // + // Handle list of arguments. + // + TIntermSequence &sequenceVector = aggrNode->getSequence() ; // Stores the information about the parameter to the constructor + // if the structure constructor contains more than one parameter, then construct + // each parameter + + int paramCount = 0; // keeps a track of the constructor parameter number being checked + + // for each parameter to the constructor call, check to see if the right type is passed or convert them + // to the right type if possible (and allowed). + // for structure constructors, just check if the right type is passed, no conversion is allowed. + + for (TIntermSequence::iterator p = sequenceVector.begin(); + p != sequenceVector.end(); p++, paramCount++) { + if (type->isArray()) + newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true); + else if (op == EOpConstructStruct) + newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true); + else + newNode = constructBuiltIn(type, op, *p, node->getLine(), true); + + if (newNode) { + *p = newNode; + } + } + + TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line); + TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type); + if (constConstructor) + return constConstructor; + + return constructor; +} + +TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type) +{ + bool canBeFolded = areAllChildConst(aggrNode); + aggrNode->setType(type); + if (canBeFolded) { + bool returnVal = false; + ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()]; + if (aggrNode->getSequence().size() == 1) { + returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type, true); + } + else { + returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type); + } + if (returnVal) + return 0; + + return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine()); + } + + return 0; +} + +// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value +// for the parameter to the constructor (passed to this function). Essentially, it converts +// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a +// float, then float is converted to int. +// +// Returns 0 for an error or the constructed node. +// +TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, TSourceLoc line, bool subset) +{ + TIntermTyped* newNode; + TOperator basicOp; + + // + // First, convert types as needed. + // + switch (op) { + case EOpConstructVec2: + case EOpConstructVec3: + case EOpConstructVec4: + case EOpConstructMat2: + case EOpConstructMat3: + case EOpConstructMat4: + case EOpConstructFloat: + basicOp = EOpConstructFloat; + break; + + case EOpConstructIVec2: + case EOpConstructIVec3: + case EOpConstructIVec4: + case EOpConstructInt: + basicOp = EOpConstructInt; + break; + + case EOpConstructBVec2: + case EOpConstructBVec3: + case EOpConstructBVec4: + case EOpConstructBool: + basicOp = EOpConstructBool; + break; + + default: + error(line, "unsupported construction", "", ""); + recover(); + + return 0; + } + newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable); + if (newNode == 0) { + error(line, "can't convert", "constructor", ""); + return 0; + } + + // + // Now, if there still isn't an operation to do the construction, and we need one, add one. + // + + // Otherwise, skip out early. + if (subset || (newNode != node && newNode->getType() == *type)) + return newNode; + + // setAggregateOperator will insert a new node for the constructor, as needed. + return intermediate.setAggregateOperator(newNode, op, line); +} + +// This function tests for the type of the parameters to the structures constructors. Raises +// an error message if the expected type does not match the parameter passed to the constructor. +// +// Returns 0 for an error or the input node itself if the expected and the given parameter types match. +// +TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset) +{ + if (*type == node->getAsTyped()->getType()) { + if (subset) + return node->getAsTyped(); + else + return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line); + } else { + 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; +} + +// +// Parse an array of strings using yyparse. +// +// Returns 0 for success. +// +int PaParseStrings(int count, const char* const string[], const int length[], + TParseContext* context) { + if ((count == 0) || (string == NULL)) + return 1; + + // setup preprocessor. + if (InitPreprocessor()) + return 1; + DefineExtensionMacros(context->extensionBehavior); + + if (glslang_initialize(context)) + return 1; + + glslang_scan(count, string, length, context); + int error = glslang_parse(context); + + glslang_finalize(context); + FinalizePreprocessor(); + return (error == 0) && (context->numErrors == 0) ? 0 : 1; +} + +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 000000000..8637d890b --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/ParseHelper.h @@ -0,0 +1,119 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +#ifndef _PARSER_HELPER_INCLUDED_ +#define _PARSER_HELPER_INCLUDED_ + +#include "compiler/ExtensionBehavior.h" +#include "compiler/localintermediate.h" +#include "compiler/ShHandle.h" +#include "compiler/SymbolTable.h" + +struct TMatrixFields { + bool wholeRow; + bool wholeCol; + int row; + int col; +}; + +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, TExtensionBehavior& ext, TIntermediate& interm, ShShaderType type, ShShaderSpec spec, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) : + intermediate(interm), symbolTable(symt), extensionBehavior(ext), infoSink(is), shaderType(type), shaderSpec(spec), compileOptions(options), checksPrecisionErrors(checksPrecErrors), sourcePath(sourcePath), treeRoot(0), + recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0), + inTypeParen(false), scanner(NULL), contextPragma(true, false) { } + TIntermediate& intermediate; // to hold and build a parse tree + TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed + TExtensionBehavior& extensionBehavior; // mapping between supported extensions and current behavior. + TInfoSink& infoSink; + ShShaderType shaderType; // vertex or fragment language (future: pack or unpack) + ShShaderSpec shaderSpec; // The language specification compiler conforms to - GLES2 or WebGL. + int compileOptions; + const char* sourcePath; // Path of source file or NULL. + TIntermNode* treeRoot; // root of parse tree being created + bool 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 + bool checksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit. + + void error(TSourceLoc loc, const char *reason, const char* token, + const char* extraInfoFormat, ...); + void warning(TSourceLoc loc, const char* reason, const char* token, + const char* extraInfoFormat, ...); + 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, TVariable*& variable); + bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type); + bool extensionErrorCheck(int line, const TString&); + 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); + void* scanner; + struct TPragma contextPragma; + TString HashErrMsg; + bool AfterEOF; +}; + +int PaParseStrings(int count, const char* const string[], const int length[], + TParseContext* context); + +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 000000000..e286c7d20 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.cpp @@ -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. +// + +#include "compiler/PoolAlloc.h" + +#ifndef _MSC_VER +#include <stdint.h> +#endif +#include <stdio.h> + +#include "compiler/InitializeGlobals.h" +#include "compiler/osinclude.h" + +OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX; + +void InitializeGlobalPools() +{ + TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); + if (globalPools) + return; + + TThreadGlobalPools* threadData = new TThreadGlobalPools(); + threadData->globalPoolAllocator = 0; + + OS_SetTLSValue(PoolIndex, threadData); +} + +void FreeGlobalPools() +{ + // Release the allocated memory for this thread. + TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); + if (!globalPools) + return; + + delete globalPools; +} + +bool InitializePoolIndex() +{ + // Allocate a TLS index. + if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX) + return false; + + return true; +} + +void FreePoolIndex() +{ + // Release the TLS index. + OS_FreeTLSIndex(PoolIndex); +} + +TPoolAllocator& GetGlobalPoolAllocator() +{ + TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); + + return *threadData->globalPoolAllocator; +} + +void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator) +{ + TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); + + threadData->globalPoolAllocator = poolAllocator; +} + +// +// Implement the functionality of the TPoolAllocator class, which +// is documented in PoolAlloc.h. +// +TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) : + pageSize(growthIncrement), + alignment(allocationAlignment), + freeList(0), + inUseList(0), + numCalls(0), + totalBytes(0) +{ + // + // Don't allow page sizes we know are smaller than all common + // OS page sizes. + // + if (pageSize < 4*1024) + pageSize = 4*1024; + + // + // A large currentPageOffset indicates a new page needs to + // be obtained to allocate memory. + // + currentPageOffset = pageSize; + + // + // Adjust alignment to be at least pointer aligned and + // power of 2. + // + size_t minAlign = sizeof(void*); + alignment &= ~(minAlign - 1); + if (alignment < minAlign) + alignment = minAlign; + size_t a = 1; + while (a < alignment) + a <<= 1; + alignment = a; + alignmentMask = a - 1; + + // + // Align header skip + // + headerSkip = minAlign; + if (headerSkip < sizeof(tHeader)) { + headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask; + } +} + +TPoolAllocator::~TPoolAllocator() +{ + while (inUseList) { + tHeader* next = inUseList->nextPage; + inUseList->~tHeader(); + delete [] reinterpret_cast<char*>(inUseList); + inUseList = next; + } + + // We should not check the guard blocks + // here, because we did it already when the block was + // placed into the free list. + // + while (freeList) { + tHeader* next = freeList->nextPage; + delete [] reinterpret_cast<char*>(freeList); + freeList = next; + } +} + +// Support MSVC++ 6.0 +const unsigned char TAllocation::guardBlockBeginVal = 0xfb; +const unsigned char TAllocation::guardBlockEndVal = 0xfe; +const unsigned char TAllocation::userDataFill = 0xcd; + +#ifdef GUARD_BLOCKS + const size_t TAllocation::guardBlockSize = 16; +#else + const size_t TAllocation::guardBlockSize = 0; +#endif + +// +// Check a single guard block for damage +// +void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const +{ +#ifdef GUARD_BLOCKS + for (size_t x = 0; x < guardBlockSize; x++) { + if (blockMem[x] != val) { + char assertMsg[80]; + + // We don't print the assert message. It's here just to be helpful. + sprintf(assertMsg, "PoolAlloc: Damage %s %lu byte allocation at 0x%p\n", + locText, size, data()); + assert(0 && "PoolAlloc: Damage in guard block"); + } + } +#endif +} + + +void TPoolAllocator::push() +{ + tAllocState state = { currentPageOffset, inUseList }; + + stack.push_back(state); + + // + // Indicate there is no current page to allocate from. + // + currentPageOffset = pageSize; +} + +// +// Do a mass-deallocation of all the individual allocations +// that have occurred since the last push(), or since the +// last pop(), or since the object's creation. +// +// The deallocated pages are saved for future allocations. +// +void TPoolAllocator::pop() +{ + if (stack.size() < 1) + return; + + tHeader* page = stack.back().page; + currentPageOffset = stack.back().offset; + + while (inUseList != page) { + // invoke destructor to free allocation list + inUseList->~tHeader(); + + tHeader* nextInUse = inUseList->nextPage; + if (inUseList->pageCount > 1) + delete [] reinterpret_cast<char*>(inUseList); + else { + inUseList->nextPage = freeList; + freeList = inUseList; + } + inUseList = nextInUse; + } + + stack.pop_back(); +} + +// +// Do a mass-deallocation of all the individual allocations +// that have occurred. +// +void TPoolAllocator::popAll() +{ + while (stack.size() > 0) + pop(); +} + +void* TPoolAllocator::allocate(size_t numBytes) +{ + // If we are using guard blocks, all allocations are bracketed by + // them: [guardblock][allocation][guardblock]. numBytes is how + // much memory the caller asked for. allocationSize is the total + // size including guard blocks. In release build, + // guardBlockSize=0 and this all gets optimized away. + size_t allocationSize = TAllocation::allocationSize(numBytes); + + // + // Just keep some interesting statistics. + // + ++numCalls; + totalBytes += numBytes; + + // + // Do the allocation, most likely case first, for efficiency. + // This step could be moved to be inline sometime. + // + if (currentPageOffset + allocationSize <= pageSize) { + // + // Safe to allocate from currentPageOffset. + // + unsigned char* memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset; + currentPageOffset += allocationSize; + currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask; + + return initializeAllocation(inUseList, memory, numBytes); + } + + if (allocationSize + headerSkip > pageSize) { + // + // Do a multi-page allocation. Don't mix these with the others. + // The OS is efficient and allocating and free-ing multiple pages. + // + size_t numBytesToAlloc = allocationSize + headerSkip; + tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]); + if (memory == 0) + return 0; + + // Use placement-new to initialize header + new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize); + inUseList = memory; + + currentPageOffset = pageSize; // make next allocation come from a new page + + // No guard blocks for multi-page allocations (yet) + return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(memory) + headerSkip); + } + + // + // Need a simple page to allocate from. + // + tHeader* memory; + if (freeList) { + memory = freeList; + freeList = freeList->nextPage; + } else { + memory = reinterpret_cast<tHeader*>(::new char[pageSize]); + if (memory == 0) + return 0; + } + + // Use placement-new to initialize header + new(memory) tHeader(inUseList, 1); + inUseList = memory; + + unsigned char* ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip; + currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask; + + return initializeAllocation(inUseList, ret, numBytes); +} + + +// +// Check all allocations in a list for damage by calling check on each. +// +void TAllocation::checkAllocList() const +{ + for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc) + alloc->check(); +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.h b/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.h new file mode 100644 index 000000000..55e09dbc4 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.h @@ -0,0 +1,300 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _POOLALLOC_INCLUDED_ +#define _POOLALLOC_INCLUDED_ + +#ifdef _DEBUG +#define GUARD_BLOCKS // define to enable guard block sanity checking +#endif + +// +// This header defines an allocator that can be used to efficiently +// allocate a large number of small requests for heap memory, with the +// intention that they are not individually deallocated, but rather +// collectively deallocated at one time. +// +// This simultaneously +// +// * Makes each individual allocation much more efficient; the +// typical allocation is trivial. +// * Completely avoids the cost of doing individual deallocation. +// * Saves the trouble of tracking down and plugging a large class of leaks. +// +// Individual classes can use this allocator by supplying their own +// new and delete methods. +// +// STL containers can use this allocator by using the pool_allocator +// class as the allocator (second) template argument. +// + +#include <stddef.h> +#include <string.h> +#include <vector> + +// If we are using guard blocks, we must track each indivual +// allocation. If we aren't using guard blocks, these +// never get instantiated, so won't have any impact. +// + +class TAllocation { +public: + TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) : + size(size), mem(mem), prevAlloc(prev) { + // Allocations are bracketed: + // [allocationHeader][initialGuardBlock][userData][finalGuardBlock] + // This would be cleaner with if (guardBlockSize)..., but that + // makes the compiler print warnings about 0 length memsets, + // even with the if() protecting them. +#ifdef GUARD_BLOCKS + memset(preGuard(), guardBlockBeginVal, guardBlockSize); + memset(data(), userDataFill, size); + memset(postGuard(), guardBlockEndVal, guardBlockSize); +#endif + } + + void check() const { + checkGuardBlock(preGuard(), guardBlockBeginVal, "before"); + checkGuardBlock(postGuard(), guardBlockEndVal, "after"); + } + + void checkAllocList() const; + + // Return total size needed to accomodate user buffer of 'size', + // plus our tracking data. + inline static size_t allocationSize(size_t size) { + return size + 2 * guardBlockSize + headerSize(); + } + + // Offset from surrounding buffer to get to user data buffer. + inline static unsigned char* offsetAllocation(unsigned char* m) { + return m + guardBlockSize + headerSize(); + } + +private: + void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const; + + // Find offsets to pre and post guard blocks, and user data buffer + unsigned char* preGuard() const { return mem + headerSize(); } + unsigned char* data() const { return preGuard() + guardBlockSize; } + unsigned char* postGuard() const { return data() + size; } + + size_t size; // size of the user data area + unsigned char* mem; // beginning of our allocation (pts to header) + TAllocation* prevAlloc; // prior allocation in the chain + + // Support MSVC++ 6.0 + const static unsigned char guardBlockBeginVal; + const static unsigned char guardBlockEndVal; + const static unsigned char userDataFill; + + const static size_t guardBlockSize; +#ifdef GUARD_BLOCKS + inline static size_t headerSize() { return sizeof(TAllocation); } +#else + inline static size_t headerSize() { return 0; } +#endif +}; + +// +// There are several stacks. One is to track the pushing and popping +// of the user, and not yet implemented. The others are simply a +// repositories of free pages or used pages. +// +// Page stacks are linked together with a simple header at the beginning +// of each allocation obtained from the underlying OS. Multi-page allocations +// are returned to the OS. Individual page allocations are kept for future +// re-use. +// +// The "page size" used is not, nor must it match, the underlying OS +// page size. But, having it be about that size or equal to a set of +// pages is likely most optimal. +// +class TPoolAllocator { +public: + TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16); + + // + // Don't call the destructor just to free up the memory, call pop() + // + ~TPoolAllocator(); + + // + // Call push() to establish a new place to pop memory too. Does not + // have to be called to get things started. + // + void push(); + + // + // Call pop() to free all memory allocated since the last call to push(), + // or if no last call to push, frees all memory since first allocation. + // + void pop(); + + // + // Call popAll() to free all memory allocated. + // + void popAll(); + + // + // Call allocate() to actually acquire memory. Returns 0 if no memory + // available, otherwise a properly aligned pointer to 'numBytes' of memory. + // + void* allocate(size_t numBytes); + + // + // There is no deallocate. The point of this class is that + // deallocation can be skipped by the user of it, as the model + // of use is to simultaneously deallocate everything at once + // by calling pop(), and to not have to solve memory leak problems. + // + +protected: + friend struct tHeader; + + struct tHeader { + tHeader(tHeader* nextPage, size_t pageCount) : + nextPage(nextPage), + pageCount(pageCount) +#ifdef GUARD_BLOCKS + , lastAllocation(0) +#endif + { } + + ~tHeader() { +#ifdef GUARD_BLOCKS + if (lastAllocation) + lastAllocation->checkAllocList(); +#endif + } + + tHeader* nextPage; + size_t pageCount; +#ifdef GUARD_BLOCKS + TAllocation* lastAllocation; +#endif + }; + + struct tAllocState { + size_t offset; + tHeader* page; + }; + typedef std::vector<tAllocState> tAllocStack; + + // Track allocations if and only if we're using guard blocks + void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) { +#ifdef GUARD_BLOCKS + new(memory) TAllocation(numBytes, memory, block->lastAllocation); + block->lastAllocation = reinterpret_cast<TAllocation*>(memory); +#endif + // This is optimized entirely away if GUARD_BLOCKS is not defined. + return TAllocation::offsetAllocation(memory); + } + + size_t pageSize; // granularity of allocation from the OS + size_t alignment; // all returned allocations will be aligned at + // this granularity, which will be a power of 2 + size_t alignmentMask; + size_t headerSkip; // amount of memory to skip to make room for the + // header (basically, size of header, rounded + // up to make it aligned + size_t currentPageOffset; // next offset in top of inUseList to allocate from + tHeader* freeList; // list of popped memory + tHeader* inUseList; // list of all memory currently being used + tAllocStack stack; // stack of where to allocate from, to partition pool + + int numCalls; // just an interesting statistic + size_t totalBytes; // just an interesting statistic +private: + TPoolAllocator& operator=(const TPoolAllocator&); // dont allow assignment operator + TPoolAllocator(const TPoolAllocator&); // dont allow default copy constructor +}; + + +// +// There could potentially be many pools with pops happening at +// different times. But a simple use is to have a global pop +// with everyone using the same global allocator. +// +extern TPoolAllocator& GetGlobalPoolAllocator(); +extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator); +#define GlobalPoolAllocator GetGlobalPoolAllocator() + +struct TThreadGlobalPools +{ + TPoolAllocator* globalPoolAllocator; +}; + +// +// This STL compatible allocator is intended to be used as the allocator +// parameter to templatized STL containers, like vector and map. +// +// It will use the pools for allocation, and not +// do any deallocation, but will still do destruction. +// +template<class T> +class pool_allocator { +public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + + template<class Other> + struct rebind { + typedef pool_allocator<Other> other; + }; + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + + pool_allocator() : allocator(GlobalPoolAllocator) { } + pool_allocator(TPoolAllocator& a) : allocator(a) { } + pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { } + + template<class Other> + pool_allocator(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 000000000..92a6874eb --- /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 000000000..872a06f72 --- /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 000000000..a4b8c1e63 --- /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 000000000..97a821679 --- /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/SearchSymbol.cpp b/Source/ThirdParty/ANGLE/src/compiler/SearchSymbol.cpp new file mode 100644 index 000000000..9368f1a4f --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/SearchSymbol.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. +// +// SearchSymbol is an AST traverser to detect the use of a given symbol name +// + +#include "compiler/SearchSymbol.h" + +#include "compiler/InfoSink.h" +#include "compiler/OutputHLSL.h" + +namespace sh +{ +SearchSymbol::SearchSymbol(const TString &symbol) : mSymbol(symbol) +{ + match = false; +} + +void SearchSymbol::traverse(TIntermNode *node) +{ + node->traverse(this); +} + +void SearchSymbol::visitSymbol(TIntermSymbol *symbolNode) +{ + if (symbolNode->getSymbol() == mSymbol) + { + match = true; + } +} + +bool SearchSymbol::foundMatch() const +{ + return match; +} +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/SearchSymbol.h b/Source/ThirdParty/ANGLE/src/compiler/SearchSymbol.h new file mode 100644 index 000000000..6bc0b90fe --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/SearchSymbol.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. +// +// SearchSymbol is an AST traverser to detect the use of a given symbol name +// + +#ifndef COMPILER_SEARCHSYMBOL_H_ +#define COMPILER_SEARCHSYMBOL_H_ + +#include "compiler/intermediate.h" +#include "compiler/ParseHelper.h" + +namespace sh +{ +class SearchSymbol : public TIntermTraverser +{ + public: + SearchSymbol(const TString &symbol); + + void traverse(TIntermNode *node); + void visitSymbol(TIntermSymbol *symbolNode); + + bool foundMatch() const; + + protected: + const TString &mSymbol; + bool match; +}; +} + +#endif // COMPILER_SEARCHSYMBOL_H_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/ShHandle.h b/Source/ThirdParty/ANGLE/src/compiler/ShHandle.h new file mode 100644 index 000000000..bf61d29e5 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/ShHandle.h @@ -0,0 +1,113 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _SHHANDLE_INCLUDED_ +#define _SHHANDLE_INCLUDED_ + +// +// Machine independent part of the compiler private objects +// sent as ShHandle to the driver. +// +// This should not be included by driver code. +// + +#include "GLSLANG/ShaderLang.h" + +#include "compiler/ExtensionBehavior.h" +#include "compiler/InfoSink.h" +#include "compiler/SymbolTable.h" +#include "compiler/VariableInfo.h" + +class TCompiler; + +// +// The base class used to back handles returned to the driver. +// +class TShHandleBase { +public: + TShHandleBase(); + virtual ~TShHandleBase(); + virtual TCompiler* getAsCompiler() { return 0; } + +protected: + // Memory allocator. Allocates and tracks memory required by the compiler. + // Deallocates all memory when compiler is destructed. + TPoolAllocator allocator; +}; + +// +// The base class for the machine dependent compiler to derive from +// for managing object code from the compile. +// +class TCompiler : public TShHandleBase { +public: + TCompiler(ShShaderType type, ShShaderSpec spec); + virtual ~TCompiler(); + virtual TCompiler* getAsCompiler() { return this; } + + bool Init(const ShBuiltInResources& resources); + bool compile(const char* const shaderStrings[], + const int numStrings, + int compileOptions); + + // Get results of the last compilation. + TInfoSink& getInfoSink() { return infoSink; } + const TVariableInfoList& getAttribs() const { return attribs; } + const TVariableInfoList& getUniforms() const { return uniforms; } + int getMappedNameMaxLength() const; + +protected: + ShShaderType getShaderType() const { return shaderType; } + ShShaderSpec getShaderSpec() const { return shaderSpec; } + // Initialize symbol-table with built-in symbols. + bool InitBuiltInSymbolTable(const ShBuiltInResources& resources); + // Clears the results from the previous compilation. + void clearResults(); + // Returns true if the given shader does not exceed the minimum + // functionality mandated in GLSL 1.0 spec Appendix A. + bool validateLimitations(TIntermNode* root); + // Collect info for all attribs and uniforms. + void collectAttribsUniforms(TIntermNode* root); + // Map long variable names into shorter ones. + void mapLongVariableNames(TIntermNode* root); + // Translate to object code. + virtual void translate(TIntermNode* root) = 0; + // Get built-in extensions with default behavior. + const TExtensionBehavior& getExtensionBehavior() const; + +private: + ShShaderType shaderType; + ShShaderSpec shaderSpec; + + // Built-in symbol table for the given language, spec, and resources. + // It is preserved from compile-to-compile. + TSymbolTable symbolTable; + // Built-in extensions with default behavior. + TExtensionBehavior extensionBehavior; + + // Results of compilation. + TInfoSink infoSink; // Output sink. + TVariableInfoList attribs; // Active attributes in the compiled shader. + TVariableInfoList uniforms; // Active uniforms in the compiled shader. + + // Pair of long varying varibale name <originalName, mappedName>. + TMap<TString, TString> varyingLongNameMap; +}; + +// +// This is the interface between the machine independent code +// and the machine dependent code. +// +// The machine dependent code should derive from the classes +// above. Then Construct*() and Delete*() will create and +// destroy the machine dependent objects, which contain the +// above machine independent information. +// +TCompiler* ConstructCompiler( + ShShaderType type, ShShaderSpec spec, ShShaderOutput output); +void DeleteCompiler(TCompiler*); + +#endif // _SHHANDLE_INCLUDED_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/ShaderLang.cpp b/Source/ThirdParty/ANGLE/src/compiler/ShaderLang.cpp new file mode 100644 index 000000000..ab8799c65 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/ShaderLang.cpp @@ -0,0 +1,262 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// +// Implement the top-level of interface to the compiler, +// as defined in ShaderLang.h +// + +#include "GLSLANG/ShaderLang.h" + +#include "compiler/InitializeDll.h" +#include "compiler/ShHandle.h" + +// +// This is the platform independent interface between an OGL driver +// and the shading language compiler. +// + +static int getVariableMaxLength(const TVariableInfoList& varList) +{ + TString::size_type maxLen = 0; + for (TVariableInfoList::const_iterator i = varList.begin(); + i != varList.end(); ++i) + { + maxLen = std::max(maxLen, i->name.size()); + } + // Add 1 to include null-termination character. + return static_cast<int>(maxLen) + 1; +} + +static void getVariableInfo(ShShaderInfo varType, + const ShHandle handle, + int index, + int* length, + int* size, + ShDataType* type, + char* name, + char* mappedName) +{ + if (!handle || !size || !type || !name) + return; + ASSERT((varType == SH_ACTIVE_ATTRIBUTES) || + (varType == SH_ACTIVE_UNIFORMS)); + + TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle); + TCompiler* compiler = base->getAsCompiler(); + if (compiler == 0) + return; + + const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ? + compiler->getAttribs() : compiler->getUniforms(); + if (index < 0 || index >= static_cast<int>(varList.size())) + return; + + const TVariableInfo& varInfo = varList[index]; + if (length) *length = varInfo.name.size(); + *size = varInfo.size; + *type = varInfo.type; + strcpy(name, varInfo.name.c_str()); + if (mappedName) + strcpy(mappedName, varInfo.mappedName.c_str()); +} + +// +// Driver must call this first, once, before doing any other +// compiler operations. +// +int ShInitialize() +{ + if (!InitProcess()) + return 0; + + return 1; +} + +// +// Cleanup symbol tables +// +int ShFinalize() +{ + if (!DetachProcess()) + return 0; + + return 1; +} + +// +// Initialize built-in resources with minimum expected values. +// +void ShInitBuiltInResources(ShBuiltInResources* resources) +{ + // Constants. + resources->MaxVertexAttribs = 8; + resources->MaxVertexUniformVectors = 128; + resources->MaxVaryingVectors = 8; + resources->MaxVertexTextureImageUnits = 0; + resources->MaxCombinedTextureImageUnits = 8; + resources->MaxTextureImageUnits = 8; + resources->MaxFragmentUniformVectors = 16; + resources->MaxDrawBuffers = 1; + + // Extensions. + resources->OES_standard_derivatives = 0; +} + +// +// Driver calls these to create and destroy compiler objects. +// +ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, + ShShaderOutput output, + const ShBuiltInResources* resources) +{ + if (!InitThread()) + return 0; + + TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output)); + TCompiler* compiler = base->getAsCompiler(); + if (compiler == 0) + return 0; + + // Generate built-in symbol table. + if (!compiler->Init(*resources)) { + ShDestruct(base); + return 0; + } + + return reinterpret_cast<void*>(base); +} + +void ShDestruct(ShHandle handle) +{ + if (handle == 0) + return; + + TShHandleBase* base = static_cast<TShHandleBase*>(handle); + + if (base->getAsCompiler()) + DeleteCompiler(base->getAsCompiler()); +} + +// +// Do an actual compile on the given strings. The result is left +// in the given compile object. +// +// Return: The return value of ShCompile is really boolean, indicating +// success or failure. +// +int ShCompile( + const ShHandle handle, + const char* const shaderStrings[], + const int numStrings, + int compileOptions) +{ + if (!InitThread()) + return 0; + + if (handle == 0) + return 0; + + TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle); + TCompiler* compiler = base->getAsCompiler(); + if (compiler == 0) + return 0; + + bool success = compiler->compile(shaderStrings, numStrings, compileOptions); + return success ? 1 : 0; +} + +void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params) +{ + if (!handle || !params) + return; + + TShHandleBase* base = static_cast<TShHandleBase*>(handle); + TCompiler* compiler = base->getAsCompiler(); + if (!compiler) return; + + switch(pname) + { + case SH_INFO_LOG_LENGTH: + *params = compiler->getInfoSink().info.size() + 1; + break; + case SH_OBJECT_CODE_LENGTH: + *params = compiler->getInfoSink().obj.size() + 1; + break; + case SH_ACTIVE_UNIFORMS: + *params = compiler->getUniforms().size(); + break; + case SH_ACTIVE_UNIFORM_MAX_LENGTH: + *params = getVariableMaxLength(compiler->getUniforms()); + break; + case SH_ACTIVE_ATTRIBUTES: + *params = compiler->getAttribs().size(); + break; + case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: + *params = getVariableMaxLength(compiler->getAttribs()); + break; + case SH_MAPPED_NAME_MAX_LENGTH: + *params = compiler->getMappedNameMaxLength(); + break; + default: UNREACHABLE(); + } +} + +// +// Return any compiler log of messages for the application. +// +void ShGetInfoLog(const ShHandle handle, char* infoLog) +{ + if (!handle || !infoLog) + return; + + TShHandleBase* base = static_cast<TShHandleBase*>(handle); + TCompiler* compiler = base->getAsCompiler(); + if (!compiler) return; + + TInfoSink& infoSink = compiler->getInfoSink(); + strcpy(infoLog, infoSink.info.c_str()); +} + +// +// Return any object code. +// +void ShGetObjectCode(const ShHandle handle, char* objCode) +{ + if (!handle || !objCode) + return; + + TShHandleBase* base = static_cast<TShHandleBase*>(handle); + TCompiler* compiler = base->getAsCompiler(); + if (!compiler) return; + + TInfoSink& infoSink = compiler->getInfoSink(); + strcpy(objCode, infoSink.obj.c_str()); +} + +void ShGetActiveAttrib(const ShHandle handle, + int index, + int* length, + int* size, + ShDataType* type, + char* name, + char* mappedName) +{ + getVariableInfo(SH_ACTIVE_ATTRIBUTES, + handle, index, length, size, type, name, mappedName); +} + +void ShGetActiveUniform(const ShHandle handle, + int index, + int* length, + int* size, + ShDataType* type, + char* name, + char* mappedName) +{ + getVariableInfo(SH_ACTIVE_UNIFORMS, + handle, index, length, size, type, name, mappedName); +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.cpp b/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.cpp new file mode 100644 index 000000000..02817d447 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.cpp @@ -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. +// + +// +// 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); + } + } +} + +// +// Change all function entries in the table with the non-mangled name +// to be related to the provided built-in extension. This is a low +// performance operation, and only intended for symbol tables that +// live across a large number of compiles. +// +void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext) +{ + for (tLevel::iterator it = level.begin(); it != level.end(); ++it) { + if (it->second->isFunction()) { + TFunction* function = static_cast<TFunction*>(it->second); + if (function->getName() == name) + function->relateToExtension(ext); + } + } +} + +TSymbol::TSymbol(const TSymbol& copyOf) +{ + name = NewPoolTString(copyOf.name->c_str()); + uniqueId = copyOf.uniqueId; +} + +TVariable::TVariable(const TVariable& copyOf, TStructureMap& remapper) : TSymbol(copyOf) +{ + type.copyType(copyOf.type, remapper); + userType = copyOf.userType; + // for builtIn symbol table level, unionArray and arrayInformation pointers should be NULL + assert(copyOf.arrayInformationType == 0); + arrayInformationType = 0; + + if (copyOf.unionArray) { + assert(!copyOf.type.getStruct()); + assert(copyOf.type.getObjectSize() == 1); + unionArray = new ConstantUnion[1]; + unionArray[0] = copyOf.unionArray[0]; + } else + unionArray = 0; +} + +TVariable* TVariable::clone(TStructureMap& remapper) +{ + TVariable *variable = new TVariable(*this, remapper); + + return variable; +} + +TFunction::TFunction(const TFunction& copyOf, TStructureMap& remapper) : TSymbol(copyOf) +{ + for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) { + TParameter param; + parameters.push_back(param); + parameters.back().copyParam(copyOf.parameters[i], remapper); + } + + returnType.copyType(copyOf.returnType, remapper); + mangledName = copyOf.mangledName; + op = copyOf.op; + defined = copyOf.defined; +} + +TFunction* TFunction::clone(TStructureMap& remapper) +{ + TFunction *function = new TFunction(*this, remapper); + + return function; +} + +TSymbolTableLevel* TSymbolTableLevel::clone(TStructureMap& remapper) +{ + TSymbolTableLevel *symTableLevel = new TSymbolTableLevel(); + tLevel::iterator iter; + for (iter = level.begin(); iter != level.end(); ++iter) { + symTableLevel->insert(*iter->second->clone(remapper)); + } + + return symTableLevel; +} + +void TSymbolTable::copyTable(const TSymbolTable& copyOf) +{ + TStructureMap remapper; + uniqueId = copyOf.uniqueId; + for (unsigned int i = 0; i < copyOf.table.size(); ++i) { + table.push_back(copyOf.table[i]->clone(remapper)); + } + for( unsigned int i = 0; i < copyOf.precisionStack.size(); i++) { + precisionStack.push_back( copyOf.precisionStack[i] ); + } +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.h b/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.h new file mode 100644 index 000000000..38bc65759 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.h @@ -0,0 +1,348 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _SYMBOL_TABLE_INCLUDED_ +#define _SYMBOL_TABLE_INCLUDED_ + +// +// Symbol table for parsing. Has these design characteristics: +// +// * Same symbol table can be used to compile many shaders, to preserve +// effort of creating and loading with the large numbers of built-in +// symbols. +// +// * Name mangling will be used to give each function a unique name +// so that symbol table lookups are never ambiguous. This allows +// a simpler symbol table structure. +// +// * Pushing and popping of scope, so symbol table will really be a stack +// of symbol tables. Searched from the top, with new inserts going into +// the top. +// +// * Constants: Compile time constant symbols will keep their values +// in the symbol table. The parser can substitute constants at parse +// time, including doing constant folding and constant propagation. +// +// * No temporaries: Temporaries made from operations (+, --, .xy, etc.) +// are tracked in the intermediate representation, not the symbol table. +// + +#include <assert.h> + +#include "compiler/InfoSink.h" +#include "compiler/intermediate.h" + +// +// Symbol base class. (Can build functions or variables out of these...) +// +class TSymbol { +public: + POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + TSymbol(const TString *n) : name(n) { } + virtual ~TSymbol() { /* don't delete name, it's from the pool */ } + const TString& getName() const { return *name; } + virtual const TString& getMangledName() const { return getName(); } + virtual bool isFunction() const { return false; } + virtual bool isVariable() const { return false; } + void setUniqueId(int id) { uniqueId = id; } + int getUniqueId() const { return uniqueId; } + virtual void dump(TInfoSink &infoSink) const = 0; + TSymbol(const TSymbol&); + virtual TSymbol* clone(TStructureMap& remapper) = 0; + +protected: + const TString *name; + unsigned int uniqueId; // For real comparing during code generation +}; + +// +// Variable class, meaning a symbol that's not a function. +// +// There could be a separate class heirarchy for Constant variables; +// Only one of int, bool, or float, (or none) is correct for +// any particular use, but it's easy to do this way, and doesn't +// seem worth having separate classes, and "getConst" can't simply return +// different values for different types polymorphically, so this is +// just simple and pragmatic. +// +class TVariable : public TSymbol { +public: + TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { } + virtual ~TVariable() { } + virtual bool isVariable() const { return true; } + TType& getType() { return type; } + const TType& getType() const { return type; } + bool isUserType() const { return userType; } + void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); } + void updateArrayInformationType(TType *t) { arrayInformationType = t; } + TType* getArrayInformationType() { return arrayInformationType; } + + virtual void dump(TInfoSink &infoSink) const; + + ConstantUnion* getConstPointer() + { + if (!unionArray) + unionArray = new ConstantUnion[type.getObjectSize()]; + + return unionArray; + } + + ConstantUnion* getConstPointer() const { return unionArray; } + + void shareConstPointer( ConstantUnion *constArray) + { + if (unionArray == constArray) + return; + + delete[] unionArray; + unionArray = constArray; + } + TVariable(const TVariable&, TStructureMap& remapper); // copy constructor + virtual TVariable* clone(TStructureMap& remapper); + +protected: + TType type; + bool userType; + // we are assuming that Pool Allocator will free the memory allocated to unionArray + // when this object is destroyed + ConstantUnion *unionArray; + TType *arrayInformationType; // this is used for updating maxArraySize in all the references to a given symbol +}; + +// +// The function sub-class of symbols and the parser will need to +// share this definition of a function parameter. +// +struct TParameter { + TString *name; + TType* type; + void copyParam(const TParameter& param, TStructureMap& remapper) + { + name = NewPoolTString(param.name->c_str()); + type = param.type->clone(remapper); + } +}; + +// +// The function sub-class of a symbol. +// +class TFunction : public TSymbol { +public: + TFunction(TOperator o) : + TSymbol(0), + returnType(TType(EbtVoid, EbpUndefined)), + op(o), + defined(false) { } + TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) : + TSymbol(name), + returnType(retType), + mangledName(TFunction::mangleName(*name)), + op(tOp), + defined(false) { } + virtual ~TFunction(); + virtual bool isFunction() const { return true; } + + static TString mangleName(const TString& name) { return name + '('; } + static TString unmangleName(const TString& mangledName) + { + return TString(mangledName.c_str(), mangledName.find_first_of('(')); + } + + void addParameter(TParameter& p) + { + parameters.push_back(p); + mangledName = mangledName + p.type->getMangledName(); + } + + const TString& getMangledName() const { return mangledName; } + const TType& getReturnType() const { return returnType; } + + void relateToOperator(TOperator o) { op = o; } + TOperator getBuiltInOp() const { return op; } + + void relateToExtension(const TString& ext) { extension = ext; } + const TString& getExtension() const { return extension; } + + void setDefined() { defined = true; } + bool isDefined() { return defined; } + + int getParamCount() const { return static_cast<int>(parameters.size()); } + const TParameter& getParam(int i) const { return parameters[i]; } + + virtual void dump(TInfoSink &infoSink) const; + TFunction(const TFunction&, TStructureMap& remapper); + virtual TFunction* clone(TStructureMap& remapper); + +protected: + typedef TVector<TParameter> TParamList; + TParamList parameters; + TType returnType; + TString mangledName; + TOperator op; + TString extension; + bool defined; +}; + + +class TSymbolTableLevel { +public: + typedef TMap<TString, TSymbol*> tLevel; + typedef tLevel::const_iterator const_iterator; + typedef const tLevel::value_type tLevelPair; + typedef std::pair<tLevel::iterator, bool> tInsertResult; + + POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + TSymbolTableLevel() { } + ~TSymbolTableLevel(); + + bool insert(TSymbol& symbol) + { + // + // returning true means symbol was added to the table + // + tInsertResult result; + result = level.insert(tLevelPair(symbol.getMangledName(), &symbol)); + + return result.second; + } + + TSymbol* find(const TString& name) const + { + tLevel::const_iterator it = level.find(name); + if (it == level.end()) + return 0; + else + return (*it).second; + } + + const_iterator begin() const + { + return level.begin(); + } + + const_iterator end() const + { + return level.end(); + } + + void relateToOperator(const char* name, TOperator op); + void relateToExtension(const char* name, const TString& ext); + void dump(TInfoSink &infoSink) const; + TSymbolTableLevel* clone(TStructureMap& remapper); + +protected: + tLevel level; +}; + +class TSymbolTable { +public: + TSymbolTable() : uniqueId(0) + { + // + // The symbol table cannot be used until push() is called, but + // the lack of an initial call to push() can be used to detect + // that the symbol table has not been preloaded with built-ins. + // + } + + ~TSymbolTable() + { + // level 0 is always built In symbols, so we never pop that out + while (table.size() > 1) + pop(); + } + + // + // When the symbol table is initialized with the built-ins, there should + // 'push' calls, so that built-ins are at level 0 and the shader + // globals are at level 1. + // + bool isEmpty() { return table.size() == 0; } + bool atBuiltInLevel() { return table.size() == 1; } + bool atGlobalLevel() { return table.size() <= 2; } + void push() + { + table.push_back(new TSymbolTableLevel); + precisionStack.push_back( PrecisionStackLevel() ); + } + + void pop() + { + delete table[currentLevel()]; + table.pop_back(); + precisionStack.pop_back(); + } + + bool insert(TSymbol& symbol) + { + symbol.setUniqueId(++uniqueId); + return table[currentLevel()]->insert(symbol); + } + + TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0) + { + int level = currentLevel(); + TSymbol* symbol; + do { + symbol = table[level]->find(name); + --level; + } while (symbol == 0 && level >= 0); + level++; + if (builtIn) + *builtIn = level == 0; + if (sameScope) + *sameScope = level == currentLevel(); + return symbol; + } + + TSymbolTableLevel* getGlobalLevel() { + assert(table.size() >= 2); + return table[1]; + } + void relateToOperator(const char* name, TOperator op) { + table[0]->relateToOperator(name, op); + } + void relateToExtension(const char* name, const TString& ext) { + table[0]->relateToExtension(name, ext); + } + int getMaxSymbolId() { return uniqueId; } + void dump(TInfoSink &infoSink) const; + void copyTable(const TSymbolTable& copyOf); + + void setDefaultPrecision( TBasicType type, TPrecision prec ){ + if( type != EbtFloat && type != EbtInt ) return; // Only set default precision for int/float + int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1; + precisionStack[indexOfLastElement][type] = prec; // Uses map operator [], overwrites the current value + } + + // Searches down the precisionStack for a precision qualifier for the specified TBasicType + TPrecision getDefaultPrecision( TBasicType type){ + if( type != EbtFloat && type != EbtInt ) return EbpUndefined; + int level = static_cast<int>(precisionStack.size()) - 1; + assert( level >= 0); // Just to be safe. Should not happen. + PrecisionStackLevel::iterator it; + TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this? + while( level >= 0 ){ + it = precisionStack[level].find( type ); + if( it != precisionStack[level].end() ){ + prec = (*it).second; + break; + } + level--; + } + return prec; + } + +protected: + int currentLevel() const { return static_cast<int>(table.size()) - 1; } + + std::vector<TSymbolTableLevel*> table; + typedef std::map< TBasicType, TPrecision > PrecisionStackLevel; + std::vector< PrecisionStackLevel > precisionStack; + int uniqueId; // for unique identification in code generation +}; + +#endif // _SYMBOL_TABLE_INCLUDED_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/TranslatorESSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/TranslatorESSL.cpp new file mode 100644 index 000000000..bb201a48c --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/TranslatorESSL.cpp @@ -0,0 +1,34 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/TranslatorESSL.h" + +#include "compiler/OutputESSL.h" + +TranslatorESSL::TranslatorESSL(ShShaderType type, ShShaderSpec spec) + : TCompiler(type, spec) { +} + +void TranslatorESSL::translate(TIntermNode* root) { + TInfoSinkBase& sink = getInfoSink().obj; + + // Write built-in extension behaviors. + writeExtensionBehavior(); + + // Write translated shader. + TOutputESSL outputESSL(sink); + root->traverse(&outputESSL); +} + +void TranslatorESSL::writeExtensionBehavior() { + TInfoSinkBase& sink = getInfoSink().obj; + const TExtensionBehavior& extensionBehavior = getExtensionBehavior(); + for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin(); + iter != extensionBehavior.end(); ++iter) { + sink << "#extension " << iter->first << " : " + << getBehaviorString(iter->second) << "\n"; + } +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/TranslatorESSL.h b/Source/ThirdParty/ANGLE/src/compiler/TranslatorESSL.h new file mode 100644 index 000000000..a1196bd00 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/TranslatorESSL.h @@ -0,0 +1,23 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATORESSL_H_ +#define COMPILER_TRANSLATORESSL_H_ + +#include "compiler/ShHandle.h" + +class TranslatorESSL : public TCompiler { +public: + TranslatorESSL(ShShaderType type, ShShaderSpec spec); + +protected: + virtual void translate(TIntermNode* root); + +private: + void writeExtensionBehavior(); +}; + +#endif // COMPILER_TRANSLATORESSL_H_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.cpp new file mode 100644 index 000000000..7a63ae1f0 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.cpp @@ -0,0 +1,37 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/TranslatorGLSL.h" + +#include "compiler/OutputGLSL.h" +#include "compiler/VersionGLSL.h" + +static void writeVersion(ShShaderType type, TIntermNode* root, + TInfoSinkBase& sink) { + TVersionGLSL versionGLSL(type); + root->traverse(&versionGLSL); + int version = versionGLSL.getVersion(); + // We need to write version directive only if it is greater than 110. + // If there is no version directive in the shader, 110 is implied. + if (version > 110) { + sink << "#version " << version << "\n"; + } +} + +TranslatorGLSL::TranslatorGLSL(ShShaderType type, ShShaderSpec spec) + : TCompiler(type, spec) { +} + +void TranslatorGLSL::translate(TIntermNode* root) { + TInfoSinkBase& sink = getInfoSink().obj; + + // Write GLSL version. + writeVersion(getShaderType(), root, sink); + + // Write translated shader. + TOutputGLSL outputGLSL(sink); + root->traverse(&outputGLSL); +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.h b/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.h new file mode 100644 index 000000000..c2ce06d19 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.h @@ -0,0 +1,20 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATORGLSL_H_ +#define COMPILER_TRANSLATORGLSL_H_ + +#include "compiler/ShHandle.h" + +class TranslatorGLSL : public TCompiler { +public: + TranslatorGLSL(ShShaderType type, ShShaderSpec spec); + +protected: + virtual void translate(TIntermNode* root); +}; + +#endif // COMPILER_TRANSLATORGLSL_H_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.cpp new file mode 100644 index 000000000..96d7f1077 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.cpp @@ -0,0 +1,22 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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(ShShaderType type, ShShaderSpec spec) + : TCompiler(type, spec) +{ +} + +void TranslatorHLSL::translate(TIntermNode *root) +{ + TParseContext& parseContext = *GetGlobalParseContext(); + sh::OutputHLSL outputHLSL(parseContext); + + outputHLSL.output(); +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.h b/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.h new file mode 100644 index 000000000..c3f672ba9 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.h @@ -0,0 +1,20 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATORHLSL_H_ +#define COMPILER_TRANSLATORHLSL_H_ + +#include "compiler/ShHandle.h" + +class TranslatorHLSL : public TCompiler { +public: + TranslatorHLSL(ShShaderType type, ShShaderSpec spec); + +protected: + virtual void translate(TIntermNode* root); +}; + +#endif // COMPILER_TRANSLATORHLSL_H_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/Types.h b/Source/ThirdParty/ANGLE/src/compiler/Types.h new file mode 100644 index 000000000..d0fcc08b9 --- /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), + maxArraySize(0), arrayInformationType(0), structure(0), structureSize(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), + maxArraySize(0), arrayInformationType(0), structure(0), structureSize(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), + maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(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 000000000..a36c3931e --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.cpp @@ -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. +// +// UnfoldSelect is an AST traverser to output the select operator ?: as if-else statements +// + +#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->getFalseBlock()->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 000000000..de296e442 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.h @@ -0,0 +1,37 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// UnfoldSelect is an AST traverser to output the select operator ?: as if-else statements +// + +#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/ValidateLimitations.cpp b/Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.cpp new file mode 100644 index 000000000..b46e4b91b --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.cpp @@ -0,0 +1,543 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/ValidateLimitations.h" +#include "compiler/InfoSink.h" +#include "compiler/ParseHelper.h" + +namespace { +bool IsLoopIndex(const TIntermSymbol* symbol, const TLoopStack& stack) { + for (TLoopStack::const_iterator i = stack.begin(); i != stack.end(); ++i) { + if (i->index.id == symbol->getId()) + return true; + } + return false; +} + +void MarkLoopForUnroll(const TIntermSymbol* symbol, TLoopStack& stack) { + for (TLoopStack::iterator i = stack.begin(); i != stack.end(); ++i) { + if (i->index.id == symbol->getId()) { + ASSERT(i->loop != NULL); + i->loop->setUnrollFlag(true); + return; + } + } + UNREACHABLE(); +} + +// Traverses a node to check if it represents a constant index expression. +// Definition: +// constant-index-expressions are a superset of constant-expressions. +// Constant-index-expressions can include loop indices as defined in +// GLSL ES 1.0 spec, Appendix A, section 4. +// The following are constant-index-expressions: +// - Constant expressions +// - Loop indices as defined in section 4 +// - Expressions composed of both of the above +class ValidateConstIndexExpr : public TIntermTraverser { +public: + ValidateConstIndexExpr(const TLoopStack& stack) + : mValid(true), mLoopStack(stack) {} + + // Returns true if the parsed node represents a constant index expression. + bool isValid() const { return mValid; } + + virtual void visitSymbol(TIntermSymbol* symbol) { + // Only constants and loop indices are allowed in a + // constant index expression. + if (mValid) { + mValid = (symbol->getQualifier() == EvqConst) || + IsLoopIndex(symbol, mLoopStack); + } + } + virtual void visitConstantUnion(TIntermConstantUnion*) {} + virtual bool visitBinary(Visit, TIntermBinary*) { return true; } + virtual bool visitUnary(Visit, TIntermUnary*) { return true; } + virtual bool visitSelection(Visit, TIntermSelection*) { return true; } + virtual bool visitAggregate(Visit, TIntermAggregate*) { return true; } + virtual bool visitLoop(Visit, TIntermLoop*) { return true; } + virtual bool visitBranch(Visit, TIntermBranch*) { return true; } + +private: + bool mValid; + const TLoopStack& mLoopStack; +}; + +// Traverses a node to check if it uses a loop index. +// If an int loop index is used in its body as a sampler array index, +// mark the loop for unroll. +class ValidateLoopIndexExpr : public TIntermTraverser { +public: + ValidateLoopIndexExpr(TLoopStack& stack) + : mUsesFloatLoopIndex(false), + mUsesIntLoopIndex(false), + mLoopStack(stack) {} + + bool usesFloatLoopIndex() const { return mUsesFloatLoopIndex; } + bool usesIntLoopIndex() const { return mUsesIntLoopIndex; } + + virtual void visitSymbol(TIntermSymbol* symbol) { + if (IsLoopIndex(symbol, mLoopStack)) { + switch (symbol->getBasicType()) { + case EbtFloat: + mUsesFloatLoopIndex = true; + break; + case EbtInt: + mUsesIntLoopIndex = true; + MarkLoopForUnroll(symbol, mLoopStack); + break; + default: + UNREACHABLE(); + } + } + } + virtual void visitConstantUnion(TIntermConstantUnion*) {} + virtual bool visitBinary(Visit, TIntermBinary*) { return true; } + virtual bool visitUnary(Visit, TIntermUnary*) { return true; } + virtual bool visitSelection(Visit, TIntermSelection*) { return true; } + virtual bool visitAggregate(Visit, TIntermAggregate*) { return true; } + virtual bool visitLoop(Visit, TIntermLoop*) { return true; } + virtual bool visitBranch(Visit, TIntermBranch*) { return true; } + +private: + bool mUsesFloatLoopIndex; + bool mUsesIntLoopIndex; + TLoopStack& mLoopStack; +}; +} // namespace + +ValidateLimitations::ValidateLimitations(ShShaderType shaderType, + TInfoSinkBase& sink) + : mShaderType(shaderType), + mSink(sink), + mNumErrors(0) +{ +} + +void ValidateLimitations::visitSymbol(TIntermSymbol*) +{ +} + +void ValidateLimitations::visitConstantUnion(TIntermConstantUnion*) +{ +} + +bool ValidateLimitations::visitBinary(Visit, TIntermBinary* node) +{ + // Check if loop index is modified in the loop body. + validateOperation(node, node->getLeft()); + + // Check indexing. + switch (node->getOp()) { + case EOpIndexDirect: + validateIndexing(node); + break; + case EOpIndexIndirect: +#if defined(__APPLE__) + // Loop unrolling is a work-around for a Mac Cg compiler bug where it + // crashes when a sampler array's index is also the loop index. + // Once Apple fixes this bug, we should remove the code in this CL. + // See http://codereview.appspot.com/4331048/. + if ((node->getLeft() != NULL) && (node->getRight() != NULL) && + (node->getLeft()->getAsSymbolNode())) { + TIntermSymbol* symbol = node->getLeft()->getAsSymbolNode(); + if (IsSampler(symbol->getBasicType()) && symbol->isArray()) { + ValidateLoopIndexExpr validate(mLoopStack); + node->getRight()->traverse(&validate); + if (validate.usesFloatLoopIndex()) { + error(node->getLine(), + "sampler array index is float loop index", + "for"); + } + } + } +#endif + validateIndexing(node); + break; + default: break; + } + return true; +} + +bool ValidateLimitations::visitUnary(Visit, TIntermUnary* node) +{ + // Check if loop index is modified in the loop body. + validateOperation(node, node->getOperand()); + + return true; +} + +bool ValidateLimitations::visitSelection(Visit, TIntermSelection*) +{ + return true; +} + +bool ValidateLimitations::visitAggregate(Visit, TIntermAggregate* node) +{ + switch (node->getOp()) { + case EOpFunctionCall: + validateFunctionCall(node); + break; + default: + break; + } + return true; +} + +bool ValidateLimitations::visitLoop(Visit, TIntermLoop* node) +{ + if (!validateLoopType(node)) + return false; + + TLoopInfo info; + memset(&info, 0, sizeof(TLoopInfo)); + info.loop = node; + if (!validateForLoopHeader(node, &info)) + return false; + + TIntermNode* body = node->getBody(); + if (body != NULL) { + mLoopStack.push_back(info); + body->traverse(this); + mLoopStack.pop_back(); + } + + // The loop is fully processed - no need to visit children. + return false; +} + +bool ValidateLimitations::visitBranch(Visit, TIntermBranch*) +{ + return true; +} + +void ValidateLimitations::error(TSourceLoc loc, + const char *reason, const char* token) +{ + mSink.prefix(EPrefixError); + mSink.location(loc); + mSink << "'" << token << "' : " << reason << "\n"; + ++mNumErrors; +} + +bool ValidateLimitations::withinLoopBody() const +{ + return !mLoopStack.empty(); +} + +bool ValidateLimitations::isLoopIndex(const TIntermSymbol* symbol) const +{ + return IsLoopIndex(symbol, mLoopStack); +} + +bool ValidateLimitations::validateLoopType(TIntermLoop* node) { + TLoopType type = node->getType(); + if (type == ELoopFor) + return true; + + // Reject while and do-while loops. + error(node->getLine(), + "This type of loop is not allowed", + type == ELoopWhile ? "while" : "do"); + return false; +} + +bool ValidateLimitations::validateForLoopHeader(TIntermLoop* node, + TLoopInfo* info) +{ + ASSERT(node->getType() == ELoopFor); + + // + // The for statement has the form: + // for ( init-declaration ; condition ; expression ) statement + // + if (!validateForLoopInit(node, info)) + return false; + if (!validateForLoopCond(node, info)) + return false; + if (!validateForLoopExpr(node, info)) + return false; + + return true; +} + +bool ValidateLimitations::validateForLoopInit(TIntermLoop* node, + TLoopInfo* info) +{ + TIntermNode* init = node->getInit(); + if (init == NULL) { + error(node->getLine(), "Missing init declaration", "for"); + return false; + } + + // + // init-declaration has the form: + // type-specifier identifier = constant-expression + // + TIntermAggregate* decl = init->getAsAggregate(); + if ((decl == NULL) || (decl->getOp() != EOpDeclaration)) { + error(init->getLine(), "Invalid init declaration", "for"); + return false; + } + // To keep things simple do not allow declaration list. + TIntermSequence& declSeq = decl->getSequence(); + if (declSeq.size() != 1) { + error(decl->getLine(), "Invalid init declaration", "for"); + return false; + } + TIntermBinary* declInit = declSeq[0]->getAsBinaryNode(); + if ((declInit == NULL) || (declInit->getOp() != EOpInitialize)) { + error(decl->getLine(), "Invalid init declaration", "for"); + return false; + } + TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode(); + if (symbol == NULL) { + error(declInit->getLine(), "Invalid init declaration", "for"); + return false; + } + // The loop index has type int or float. + TBasicType type = symbol->getBasicType(); + if ((type != EbtInt) && (type != EbtFloat)) { + error(symbol->getLine(), + "Invalid type for loop index", getBasicString(type)); + return false; + } + // The loop index is initialized with constant expression. + if (!isConstExpr(declInit->getRight())) { + error(declInit->getLine(), + "Loop index cannot be initialized with non-constant expression", + symbol->getSymbol().c_str()); + return false; + } + + info->index.id = symbol->getId(); + return true; +} + +bool ValidateLimitations::validateForLoopCond(TIntermLoop* node, + TLoopInfo* info) +{ + TIntermNode* cond = node->getCondition(); + if (cond == NULL) { + error(node->getLine(), "Missing condition", "for"); + return false; + } + // + // condition has the form: + // loop_index relational_operator constant_expression + // + TIntermBinary* binOp = cond->getAsBinaryNode(); + if (binOp == NULL) { + error(node->getLine(), "Invalid condition", "for"); + return false; + } + // Loop index should be to the left of relational operator. + TIntermSymbol* symbol = binOp->getLeft()->getAsSymbolNode(); + if (symbol == NULL) { + error(binOp->getLine(), "Invalid condition", "for"); + return false; + } + if (symbol->getId() != info->index.id) { + error(symbol->getLine(), + "Expected loop index", symbol->getSymbol().c_str()); + return false; + } + // Relational operator is one of: > >= < <= == or !=. + switch (binOp->getOp()) { + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + break; + default: + error(binOp->getLine(), + "Invalid relational operator", + getOperatorString(binOp->getOp())); + break; + } + // Loop index must be compared with a constant. + if (!isConstExpr(binOp->getRight())) { + error(binOp->getLine(), + "Loop index cannot be compared with non-constant expression", + symbol->getSymbol().c_str()); + return false; + } + + return true; +} + +bool ValidateLimitations::validateForLoopExpr(TIntermLoop* node, + TLoopInfo* info) +{ + TIntermNode* expr = node->getExpression(); + if (expr == NULL) { + error(node->getLine(), "Missing expression", "for"); + return false; + } + + // for expression has one of the following forms: + // loop_index++ + // loop_index-- + // loop_index += constant_expression + // loop_index -= constant_expression + // ++loop_index + // --loop_index + // The last two forms are not specified in the spec, but I am assuming + // its an oversight. + TIntermUnary* unOp = expr->getAsUnaryNode(); + TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode(); + + TOperator op = EOpNull; + TIntermSymbol* symbol = NULL; + if (unOp != NULL) { + op = unOp->getOp(); + symbol = unOp->getOperand()->getAsSymbolNode(); + } else if (binOp != NULL) { + op = binOp->getOp(); + symbol = binOp->getLeft()->getAsSymbolNode(); + } + + // The operand must be loop index. + if (symbol == NULL) { + error(expr->getLine(), "Invalid expression", "for"); + return false; + } + if (symbol->getId() != info->index.id) { + error(symbol->getLine(), + "Expected loop index", symbol->getSymbol().c_str()); + return false; + } + + // The operator is one of: ++ -- += -=. + switch (op) { + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + ASSERT((unOp != NULL) && (binOp == NULL)); + break; + case EOpAddAssign: + case EOpSubAssign: + ASSERT((unOp == NULL) && (binOp != NULL)); + break; + default: + error(expr->getLine(), "Invalid operator", getOperatorString(op)); + return false; + } + + // Loop index must be incremented/decremented with a constant. + if (binOp != NULL) { + if (!isConstExpr(binOp->getRight())) { + error(binOp->getLine(), + "Loop index cannot be modified by non-constant expression", + symbol->getSymbol().c_str()); + return false; + } + } + + return true; +} + +bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node) +{ + ASSERT(node->getOp() == EOpFunctionCall); + + // If not within loop body, there is nothing to check. + if (!withinLoopBody()) + return true; + + // List of param indices for which loop indices are used as argument. + typedef std::vector<int> ParamIndex; + ParamIndex pIndex; + TIntermSequence& params = node->getSequence(); + for (TIntermSequence::size_type i = 0; i < params.size(); ++i) { + TIntermSymbol* symbol = params[i]->getAsSymbolNode(); + if (symbol && isLoopIndex(symbol)) + pIndex.push_back(i); + } + // If none of the loop indices are used as arguments, + // there is nothing to check. + if (pIndex.empty()) + return true; + + bool valid = true; + TSymbolTable& symbolTable = GlobalParseContext->symbolTable; + TSymbol* symbol = symbolTable.find(node->getName()); + ASSERT(symbol && symbol->isFunction()); + TFunction* function = static_cast<TFunction*>(symbol); + for (ParamIndex::const_iterator i = pIndex.begin(); + i != pIndex.end(); ++i) { + const TParameter& param = function->getParam(*i); + TQualifier qual = param.type->getQualifier(); + if ((qual == EvqOut) || (qual == EvqInOut)) { + error(params[*i]->getLine(), + "Loop index cannot be used as argument to a function out or inout parameter", + params[*i]->getAsSymbolNode()->getSymbol().c_str()); + valid = false; + } + } + + return valid; +} + +bool ValidateLimitations::validateOperation(TIntermOperator* node, + TIntermNode* operand) { + // Check if loop index is modified in the loop body. + if (!withinLoopBody() || !node->modifiesState()) + return true; + + const TIntermSymbol* symbol = operand->getAsSymbolNode(); + if (symbol && isLoopIndex(symbol)) { + error(node->getLine(), + "Loop index cannot be statically assigned to within the body of the loop", + symbol->getSymbol().c_str()); + } + return true; +} + +bool ValidateLimitations::isConstExpr(TIntermNode* node) +{ + ASSERT(node != NULL); + return node->getAsConstantUnion() != NULL; +} + +bool ValidateLimitations::isConstIndexExpr(TIntermNode* node) +{ + ASSERT(node != NULL); + + ValidateConstIndexExpr validate(mLoopStack); + node->traverse(&validate); + return validate.isValid(); +} + +bool ValidateLimitations::validateIndexing(TIntermBinary* node) +{ + ASSERT((node->getOp() == EOpIndexDirect) || + (node->getOp() == EOpIndexIndirect)); + + bool valid = true; + TIntermTyped* index = node->getRight(); + // The index expression must have integral type. + if (!index->isScalar() || (index->getBasicType() != EbtInt)) { + error(index->getLine(), + "Index expression must have integral type", + index->getCompleteString().c_str()); + valid = false; + } + // The index expession must be a constant-index-expression unless + // the operand is a uniform in a vertex shader. + TIntermTyped* operand = node->getLeft(); + bool skip = (mShaderType == SH_VERTEX_SHADER) && + (operand->getQualifier() == EvqUniform); + if (!skip && !isConstIndexExpr(index)) { + error(index->getLine(), "Index expression must be constant", "[]"); + valid = false; + } + return valid; +} + diff --git a/Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.h b/Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.h new file mode 100644 index 000000000..dd2e5bf09 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.h @@ -0,0 +1,63 @@ +// +// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "GLSLANG/ShaderLang.h" +#include "compiler/intermediate.h" + +class TInfoSinkBase; + +struct TLoopInfo { + struct TIndex { + int id; // symbol id. + } index; + TIntermLoop* loop; +}; +typedef TVector<TLoopInfo> TLoopStack; + +// Traverses intermediate tree to ensure that the shader does not exceed the +// minimum functionality mandated in GLSL 1.0 spec, Appendix A. +class ValidateLimitations : public TIntermTraverser { +public: + ValidateLimitations(ShShaderType shaderType, TInfoSinkBase& sink); + + int numErrors() const { return mNumErrors; } + + virtual void visitSymbol(TIntermSymbol*); + virtual void visitConstantUnion(TIntermConstantUnion*); + virtual bool visitBinary(Visit, TIntermBinary*); + virtual bool visitUnary(Visit, TIntermUnary*); + virtual bool visitSelection(Visit, TIntermSelection*); + virtual bool visitAggregate(Visit, TIntermAggregate*); + virtual bool visitLoop(Visit, TIntermLoop*); + virtual bool visitBranch(Visit, TIntermBranch*); + +private: + void error(TSourceLoc loc, const char *reason, const char* token); + + bool withinLoopBody() const; + bool isLoopIndex(const TIntermSymbol* symbol) const; + bool validateLoopType(TIntermLoop* node); + bool validateForLoopHeader(TIntermLoop* node, TLoopInfo* info); + bool validateForLoopInit(TIntermLoop* node, TLoopInfo* info); + bool validateForLoopCond(TIntermLoop* node, TLoopInfo* info); + bool validateForLoopExpr(TIntermLoop* node, TLoopInfo* info); + // Returns true if none of the loop indices is used as the argument to + // the given function out or inout parameter. + bool validateFunctionCall(TIntermAggregate* node); + bool validateOperation(TIntermOperator* node, TIntermNode* operand); + + // Returns true if indexing does not exceed the minimum functionality + // mandated in GLSL 1.0 spec, Appendix A, Section 5. + bool isConstExpr(TIntermNode* node); + bool isConstIndexExpr(TIntermNode* node); + bool validateIndexing(TIntermBinary* node); + + ShShaderType mShaderType; + TInfoSinkBase& mSink; + int mNumErrors; + TLoopStack mLoopStack; +}; + diff --git a/Source/ThirdParty/ANGLE/src/compiler/VariableInfo.cpp b/Source/ThirdParty/ANGLE/src/compiler/VariableInfo.cpp new file mode 100644 index 000000000..a13a89650 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/VariableInfo.cpp @@ -0,0 +1,220 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/VariableInfo.h" + +static TString arrayBrackets(int index) +{ + TStringStream stream; + stream << "[" << index << "]"; + return stream.str(); +} + +// Returns the data type for an attribute or uniform. +static ShDataType getVariableDataType(const TType& type) +{ + switch (type.getBasicType()) { + case EbtFloat: + if (type.isMatrix()) { + switch (type.getNominalSize()) { + case 2: return SH_FLOAT_MAT2; + case 3: return SH_FLOAT_MAT3; + case 4: return SH_FLOAT_MAT4; + default: UNREACHABLE(); + } + } else if (type.isVector()) { + switch (type.getNominalSize()) { + case 2: return SH_FLOAT_VEC2; + case 3: return SH_FLOAT_VEC3; + case 4: return SH_FLOAT_VEC4; + default: UNREACHABLE(); + } + } else { + return SH_FLOAT; + } + case EbtInt: + if (type.isMatrix()) { + UNREACHABLE(); + } else if (type.isVector()) { + switch (type.getNominalSize()) { + case 2: return SH_INT_VEC2; + case 3: return SH_INT_VEC3; + case 4: return SH_INT_VEC4; + default: UNREACHABLE(); + } + } else { + return SH_INT; + } + case EbtBool: + if (type.isMatrix()) { + UNREACHABLE(); + } else if (type.isVector()) { + switch (type.getNominalSize()) { + case 2: return SH_BOOL_VEC2; + case 3: return SH_BOOL_VEC3; + case 4: return SH_BOOL_VEC4; + default: UNREACHABLE(); + } + } else { + return SH_BOOL; + } + case EbtSampler2D: return SH_SAMPLER_2D; + case EbtSamplerCube: return SH_SAMPLER_CUBE; + default: UNREACHABLE(); + } + return SH_NONE; +} + +static void getBuiltInVariableInfo(const TType& type, + const TString& name, + const TString& mappedName, + TVariableInfoList& infoList); +static void getUserDefinedVariableInfo(const TType& type, + const TString& name, + const TString& mappedName, + TVariableInfoList& infoList); + +// Returns info for an attribute or uniform. +static void getVariableInfo(const TType& type, + const TString& name, + const TString& mappedName, + TVariableInfoList& infoList) +{ + if (type.getBasicType() == EbtStruct) { + if (type.isArray()) { + for (int i = 0; i < type.getArraySize(); ++i) { + TString lname = name + arrayBrackets(i); + TString lmappedName = mappedName + arrayBrackets(i); + getUserDefinedVariableInfo(type, lname, lmappedName, infoList); + } + } else { + getUserDefinedVariableInfo(type, name, mappedName, infoList); + } + } else { + getBuiltInVariableInfo(type, name, mappedName, infoList); + } +} + +void getBuiltInVariableInfo(const TType& type, + const TString& name, + const TString& mappedName, + TVariableInfoList& infoList) +{ + ASSERT(type.getBasicType() != EbtStruct); + + TVariableInfo varInfo; + if (type.isArray()) { + varInfo.name = (name + "[0]").c_str(); + varInfo.mappedName = (mappedName + "[0]").c_str(); + varInfo.size = type.getArraySize(); + } else { + varInfo.name = name.c_str(); + varInfo.mappedName = mappedName.c_str(); + varInfo.size = 1; + } + varInfo.type = getVariableDataType(type); + infoList.push_back(varInfo); +} + +void getUserDefinedVariableInfo(const TType& type, + const TString& name, + const TString& mappedName, + TVariableInfoList& infoList) +{ + ASSERT(type.getBasicType() == EbtStruct); + + const TTypeList* structure = type.getStruct(); + for (size_t i = 0; i < structure->size(); ++i) { + const TType* fieldType = (*structure)[i].type; + getVariableInfo(*fieldType, + name + "." + fieldType->getFieldName(), + mappedName + "." + fieldType->getFieldName(), + infoList); + } +} + +CollectAttribsUniforms::CollectAttribsUniforms(TVariableInfoList& attribs, + TVariableInfoList& uniforms) + : mAttribs(attribs), + mUniforms(uniforms) +{ +} + +// We are only interested in attribute and uniform variable declaration. +void CollectAttribsUniforms::visitSymbol(TIntermSymbol*) +{ +} + +void CollectAttribsUniforms::visitConstantUnion(TIntermConstantUnion*) +{ +} + +bool CollectAttribsUniforms::visitBinary(Visit, TIntermBinary*) +{ + return false; +} + +bool CollectAttribsUniforms::visitUnary(Visit, TIntermUnary*) +{ + return false; +} + +bool CollectAttribsUniforms::visitSelection(Visit, TIntermSelection*) +{ + return false; +} + +bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node) +{ + bool visitChildren = false; + + switch (node->getOp()) + { + case EOpSequence: + // We need to visit sequence children to get to variable declarations. + visitChildren = true; + break; + case EOpDeclaration: { + const TIntermSequence& sequence = node->getSequence(); + TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier(); + if (qualifier == EvqAttribute || qualifier == EvqUniform) + { + TVariableInfoList& infoList = qualifier == EvqAttribute ? + mAttribs : mUniforms; + for (TIntermSequence::const_iterator i = sequence.begin(); + i != sequence.end(); ++i) + { + const TIntermSymbol* variable = (*i)->getAsSymbolNode(); + // The only case in which the sequence will not contain a + // TIntermSymbol node is initialization. It will contain a + // TInterBinary node in that case. Since attributes and unifroms + // cannot be initialized in a shader, we must have only + // TIntermSymbol nodes in the sequence. + ASSERT(variable != NULL); + getVariableInfo(variable->getType(), + variable->getOriginalSymbol(), + variable->getSymbol(), + infoList); + } + } + break; + } + default: break; + } + + return visitChildren; +} + +bool CollectAttribsUniforms::visitLoop(Visit, TIntermLoop*) +{ + return false; +} + +bool CollectAttribsUniforms::visitBranch(Visit, TIntermBranch*) +{ + return false; +} + diff --git a/Source/ThirdParty/ANGLE/src/compiler/VariableInfo.h b/Source/ThirdParty/ANGLE/src/compiler/VariableInfo.h new file mode 100644 index 000000000..667acafcc --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/VariableInfo.h @@ -0,0 +1,43 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_VARIABLE_INFO_H_ +#define COMPILER_VARIABLE_INFO_H_ + +#include "GLSLANG/ShaderLang.h" +#include "compiler/intermediate.h" + +// Provides information about a variable. +// It is currently being used to store info about active attribs and uniforms. +struct TVariableInfo { + TPersistString name; + TPersistString mappedName; + ShDataType type; + int size; +}; +typedef std::vector<TVariableInfo> TVariableInfoList; + +// Traverses intermediate tree to collect all attributes and uniforms. +class CollectAttribsUniforms : public TIntermTraverser { +public: + CollectAttribsUniforms(TVariableInfoList& attribs, + TVariableInfoList& uniforms); + + virtual void visitSymbol(TIntermSymbol*); + virtual void visitConstantUnion(TIntermConstantUnion*); + virtual bool visitBinary(Visit, TIntermBinary*); + virtual bool visitUnary(Visit, TIntermUnary*); + virtual bool visitSelection(Visit, TIntermSelection*); + virtual bool visitAggregate(Visit, TIntermAggregate*); + virtual bool visitLoop(Visit, TIntermLoop*); + virtual bool visitBranch(Visit, TIntermBranch*); + +private: + TVariableInfoList& mAttribs; + TVariableInfoList& mUniforms; +}; + +#endif // COMPILER_VARIABLE_INFO_H_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/VersionGLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/VersionGLSL.cpp new file mode 100644 index 000000000..26cee0527 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/VersionGLSL.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/VersionGLSL.h" + +static const int GLSL_VERSION_110 = 110; +static const int GLSL_VERSION_120 = 120; + +// We need to scan for three things: +// 1. "invariant" keyword: This can occur in both - vertex and fragment shaders +// but only at the global scope. +// 2. "gl_PointCoord" built-in variable: This can only occur in fragment shader +// but inside any scope. +// 3. Call to a matrix constructor with another matrix as argument. +// (These constructors were reserved in GLSL version 1.10.) +// +// If it weren't for (3) then we would only need to scan the global +// scope of the vertex shader. However, we need to scan the entire +// shader in both cases. +// +// TODO(alokp): The following two cases of invariant decalaration get lost +// during parsing - they do not get carried over to the intermediate tree. +// Handle these cases: +// 1. When a pragma is used to force all output variables to be invariant: +// - #pragma STDGL invariant(all) +// 2. When a previously decalared or built-in variable is marked invariant: +// - invariant gl_Position; +// - varying vec3 color; invariant color; +// +TVersionGLSL::TVersionGLSL(ShShaderType type) + : mShaderType(type), + mVersion(GLSL_VERSION_110) +{ +} + +void TVersionGLSL::visitSymbol(TIntermSymbol* node) +{ + if (node->getSymbol() == "gl_PointCoord") + updateVersion(GLSL_VERSION_120); +} + +void TVersionGLSL::visitConstantUnion(TIntermConstantUnion*) +{ +} + +bool TVersionGLSL::visitBinary(Visit, TIntermBinary*) +{ + return true; +} + +bool TVersionGLSL::visitUnary(Visit, TIntermUnary*) +{ + return true; +} + +bool TVersionGLSL::visitSelection(Visit, TIntermSelection*) +{ + return true; +} + +bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate* node) +{ + bool visitChildren = true; + + switch (node->getOp()) { + case EOpSequence: + // We need to visit sequence children to get to global or inner scope. + visitChildren = true; + break; + case EOpDeclaration: { + const TIntermSequence& sequence = node->getSequence(); + TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier(); + if ((qualifier == EvqInvariantVaryingIn) || + (qualifier == EvqInvariantVaryingOut)) { + updateVersion(GLSL_VERSION_120); + } + break; + } + case EOpConstructMat2: + case EOpConstructMat3: + case EOpConstructMat4: { + const TIntermSequence& sequence = node->getSequence(); + if (sequence.size() == 1) { + TIntermTyped* typed = sequence.front()->getAsTyped(); + if (typed && typed->isMatrix()) { + updateVersion(GLSL_VERSION_120); + } + } + break; + } + + default: break; + } + + return visitChildren; +} + +bool TVersionGLSL::visitLoop(Visit, TIntermLoop*) +{ + return true; +} + +bool TVersionGLSL::visitBranch(Visit, TIntermBranch*) +{ + return true; +} + +void TVersionGLSL::updateVersion(int version) +{ + mVersion = std::max(version, mVersion); +} + diff --git a/Source/ThirdParty/ANGLE/src/compiler/VersionGLSL.h b/Source/ThirdParty/ANGLE/src/compiler/VersionGLSL.h new file mode 100644 index 000000000..376fcb848 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/VersionGLSL.h @@ -0,0 +1,52 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_VERSIONGLSL_H_ +#define COMPILER_VERSIONGLSL_H_ + +#include "GLSLANG/ShaderLang.h" +#include "compiler/intermediate.h" + +// Traverses the intermediate tree to return the minimum GLSL version +// required to legally access all built-in features used in the shader. +// GLSL 1.1 which is mandated by OpenGL 2.0 provides: +// - #version and #extension to declare version and extensions. +// - built-in functions refract, exp, and log. +// - updated step() to compare x < edge instead of x <= edge. +// GLSL 1.2 which is mandated by OpenGL 2.1 provides: +// - many changes to reduce differences when compared to the ES specification. +// - invariant keyword and its support. +// - c++ style name hiding rules. +// - built-in variable gl_PointCoord for fragment shaders. +// - matrix constructors taking matrix as argument. +// +class TVersionGLSL : public TIntermTraverser { +public: + TVersionGLSL(ShShaderType type); + + // Returns 120 if "invariant" keyword, "gl_PointCoord", or + // matrix/matrix constructors are used in the shader. Else 110 is + // returned. + int getVersion() { return mVersion; } + + virtual void visitSymbol(TIntermSymbol*); + virtual void visitConstantUnion(TIntermConstantUnion*); + virtual bool visitBinary(Visit, TIntermBinary*); + virtual bool visitUnary(Visit, TIntermUnary*); + virtual bool visitSelection(Visit, TIntermSelection*); + virtual bool visitAggregate(Visit, TIntermAggregate*); + virtual bool visitLoop(Visit, TIntermLoop*); + virtual bool visitBranch(Visit, TIntermBranch*); + +protected: + void updateVersion(int version); + +private: + ShShaderType mShaderType; + int mVersion; +}; + +#endif // COMPILER_VERSIONGLSL_H_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/debug.cpp b/Source/ThirdParty/ANGLE/src/compiler/debug.cpp new file mode 100644 index 000000000..9642e1e37 --- /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 000000000..7a371516a --- /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/generate_glslang_lexer.sh b/Source/ThirdParty/ANGLE/src/compiler/generate_glslang_lexer.sh new file mode 100644 index 000000000..268479dad --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/generate_glslang_lexer.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Generates GLSL ES lexer - glslang_lex.cpp + +script_dir=$(dirname $0) +input_file=$script_dir/glslang.l +output_file=$script_dir/glslang_lex.cpp +flex --noline --nounistd --outfile=$output_file $input_file diff --git a/Source/ThirdParty/ANGLE/src/compiler/generate_glslang_parser.sh b/Source/ThirdParty/ANGLE/src/compiler/generate_glslang_parser.sh new file mode 100644 index 000000000..889f5c0db --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/generate_glslang_parser.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Generates GLSL ES parser - glslang_tab.h and glslang_tab.cpp + +script_dir=$(dirname $0) +input_file=$script_dir/glslang.y +output_header=$script_dir/glslang_tab.h +output_source=$script_dir/glslang_tab.cpp +bison --no-lines --skeleton=yacc.c --defines=$output_header --output=$output_source $input_file diff --git a/Source/ThirdParty/ANGLE/src/compiler/glslang.h b/Source/ThirdParty/ANGLE/src/compiler/glslang.h new file mode 100644 index 000000000..26f1457e8 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/glslang.h @@ -0,0 +1,16 @@ +// +// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +struct TParseContext; +extern int glslang_initialize(TParseContext* context); +extern int glslang_finalize(TParseContext* context); + +extern void glslang_scan(int count, + const char* const string[], + const int length[], + TParseContext* context); +extern int glslang_parse(TParseContext* context); + diff --git a/Source/ThirdParty/ANGLE/src/compiler/glslang.l b/Source/ThirdParty/ANGLE/src/compiler/glslang.l new file mode 100644 index 000000000..5a7c5d52a --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/glslang.l @@ -0,0 +1,570 @@ +/* +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +This file contains the Lex specification for GLSL ES. +Based on ANSI C grammar, Lex specification: +http://www.lysator.liu.se/c/ANSI-C-grammar-l.html + +IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_glslang_lexer.sh, +WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). +*/ + +%top{ +// +// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// This file is auto-generated by generate_glslang_lexer.sh. DO NOT EDIT! +} + +%{ +#include "compiler/glslang.h" +#include "compiler/ParseHelper.h" +#include "compiler/util.h" +#include "glslang_tab.h" + +/* windows only pragma */ +#ifdef _MSC_VER +#pragma warning(disable : 4102) +#endif + +#define YY_USER_ACTION yylval->lex.line = yylineno; +#define YY_INPUT(buf, result, max_size) \ + result = string_input(buf, max_size, yyscanner); + +static int string_input(char* buf, int max_size, yyscan_t yyscanner); +static int check_type(yyscan_t yyscanner); +static int reserved_word(yyscan_t yyscanner); +%} + +%option noyywrap nounput never-interactive +%option yylineno reentrant bison-bridge +%option stack +%option extra-type="TParseContext*" +%x COMMENT FIELDS + +D [0-9] +L [a-zA-Z_] +H [a-fA-F0-9] +E [Ee][+-]?{D}+ +O [0-7] + +%% + +%{ + TParseContext* context = yyextra; +%} + + /* Single-line comments */ +"//"[^\n]* ; + + /* Multi-line comments */ +"/*" { yy_push_state(COMMENT, yyscanner); } +<COMMENT>. | +<COMMENT>\n ; +<COMMENT>"*/" { yy_pop_state(yyscanner); } + +"invariant" { return(INVARIANT); } +"highp" { return(HIGH_PRECISION); } +"mediump" { return(MEDIUM_PRECISION); } +"lowp" { return(LOW_PRECISION); } +"precision" { return(PRECISION); } + +"attribute" { return(ATTRIBUTE); } +"const" { return(CONST_QUAL); } +"uniform" { return(UNIFORM); } +"varying" { return(VARYING); } + +"break" { return(BREAK); } +"continue" { return(CONTINUE); } +"do" { return(DO); } +"for" { return(FOR); } +"while" { return(WHILE); } + +"if" { return(IF); } +"else" { return(ELSE); } + +"in" { return(IN_QUAL); } +"out" { return(OUT_QUAL); } +"inout" { return(INOUT_QUAL); } + +"float" { context->lexAfterType = true; return(FLOAT_TYPE); } +"int" { context->lexAfterType = true; return(INT_TYPE); } +"void" { context->lexAfterType = true; return(VOID_TYPE); } +"bool" { context->lexAfterType = true; return(BOOL_TYPE); } +"true" { yylval->lex.b = true; return(BOOLCONSTANT); } +"false" { yylval->lex.b = false; return(BOOLCONSTANT); } + +"discard" { return(DISCARD); } +"return" { return(RETURN); } + +"mat2" { context->lexAfterType = true; return(MATRIX2); } +"mat3" { context->lexAfterType = true; return(MATRIX3); } +"mat4" { context->lexAfterType = true; return(MATRIX4); } + +"vec2" { context->lexAfterType = true; return (VEC2); } +"vec3" { context->lexAfterType = true; return (VEC3); } +"vec4" { context->lexAfterType = true; return (VEC4); } +"ivec2" { context->lexAfterType = true; return (IVEC2); } +"ivec3" { context->lexAfterType = true; return (IVEC3); } +"ivec4" { context->lexAfterType = true; return (IVEC4); } +"bvec2" { context->lexAfterType = true; return (BVEC2); } +"bvec3" { context->lexAfterType = true; return (BVEC3); } +"bvec4" { context->lexAfterType = true; return (BVEC4); } + +"sampler2D" { context->lexAfterType = true; return SAMPLER2D; } +"samplerCube" { context->lexAfterType = true; return SAMPLERCUBE; } + +"struct" { context->lexAfterType = true; return(STRUCT); } + +"asm" { return reserved_word(yyscanner); } + +"class" { return reserved_word(yyscanner); } +"union" { return reserved_word(yyscanner); } +"enum" { return reserved_word(yyscanner); } +"typedef" { return reserved_word(yyscanner); } +"template" { return reserved_word(yyscanner); } +"this" { return reserved_word(yyscanner); } +"packed" { return reserved_word(yyscanner); } + +"goto" { return reserved_word(yyscanner); } +"switch" { return reserved_word(yyscanner); } +"default" { return reserved_word(yyscanner); } + +"inline" { return reserved_word(yyscanner); } +"noinline" { return reserved_word(yyscanner); } +"volatile" { return reserved_word(yyscanner); } +"public" { return reserved_word(yyscanner); } +"static" { return reserved_word(yyscanner); } +"extern" { return reserved_word(yyscanner); } +"external" { return reserved_word(yyscanner); } +"interface" { return reserved_word(yyscanner); } + +"long" { return reserved_word(yyscanner); } +"short" { return reserved_word(yyscanner); } +"double" { return reserved_word(yyscanner); } +"half" { return reserved_word(yyscanner); } +"fixed" { return reserved_word(yyscanner); } +"unsigned" { return reserved_word(yyscanner); } + +"input" { return reserved_word(yyscanner); } +"output" { return reserved_word(yyscanner); } + +"hvec2" { return reserved_word(yyscanner); } +"hvec3" { return reserved_word(yyscanner); } +"hvec4" { return reserved_word(yyscanner); } +"fvec2" { return reserved_word(yyscanner); } +"fvec3" { return reserved_word(yyscanner); } +"fvec4" { return reserved_word(yyscanner); } +"dvec2" { return reserved_word(yyscanner); } +"dvec3" { return reserved_word(yyscanner); } +"dvec4" { return reserved_word(yyscanner); } + +"sizeof" { return reserved_word(yyscanner); } +"cast" { return reserved_word(yyscanner); } + +"namespace" { return reserved_word(yyscanner); } +"using" { return reserved_word(yyscanner); } + +{L}({L}|{D})* { + yylval->lex.string = NewPoolTString(yytext); + return check_type(yyscanner); +} + +0[xX]{H}+ { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } +0{O}+ { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } +0{D}+ { context->error(yylineno, "Invalid Octal number.", yytext, "", ""); context->recover(); return 0;} +{D}+ { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } + +{D}+{E} { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); } +{D}+"."{D}*({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); } +"."{D}+({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); } + +"+=" { return(ADD_ASSIGN); } +"-=" { return(SUB_ASSIGN); } +"*=" { return(MUL_ASSIGN); } +"/=" { return(DIV_ASSIGN); } +"%=" { return(MOD_ASSIGN); } +"<<=" { return(LEFT_ASSIGN); } +">>=" { return(RIGHT_ASSIGN); } +"&=" { return(AND_ASSIGN); } +"^=" { return(XOR_ASSIGN); } +"|=" { return(OR_ASSIGN); } + +"++" { return(INC_OP); } +"--" { return(DEC_OP); } +"&&" { return(AND_OP); } +"||" { return(OR_OP); } +"^^" { return(XOR_OP); } +"<=" { return(LE_OP); } +">=" { return(GE_OP); } +"==" { return(EQ_OP); } +"!=" { return(NE_OP); } +"<<" { return(LEFT_OP); } +">>" { return(RIGHT_OP); } +";" { context->lexAfterType = false; return(SEMICOLON); } +("{"|"<%") { context->lexAfterType = false; return(LEFT_BRACE); } +("}"|"%>") { return(RIGHT_BRACE); } +"," { if (context->inTypeParen) context->lexAfterType = false; return(COMMA); } +":" { return(COLON); } +"=" { context->lexAfterType = false; return(EQUAL); } +"(" { context->lexAfterType = false; context->inTypeParen = true; return(LEFT_PAREN); } +")" { context->inTypeParen = false; return(RIGHT_PAREN); } +("["|"<:") { return(LEFT_BRACKET); } +("]"|":>") { return(RIGHT_BRACKET); } +"." { BEGIN(FIELDS); return(DOT); } +"!" { return(BANG); } +"-" { return(DASH); } +"~" { return(TILDE); } +"+" { return(PLUS); } +"*" { return(STAR); } +"/" { return(SLASH); } +"%" { return(PERCENT); } +"<" { return(LEFT_ANGLE); } +">" { return(RIGHT_ANGLE); } +"|" { return(VERTICAL_BAR); } +"^" { return(CARET); } +"&" { return(AMPERSAND); } +"?" { return(QUESTION); } + +<FIELDS>{L}({L}|{D})* { + BEGIN(INITIAL); + yylval->lex.string = NewPoolTString(yytext); + return FIELD_SELECTION; +} +<FIELDS>[ \t\v\f\r] {} + +[ \t\v\n\f\r] { } +<*><<EOF>> { context->AfterEOF = true; yyterminate(); } +<*>. { context->warning(yylineno, "Unknown char", yytext, ""); return 0; } + +%% + +extern "C" { +// Preprocessor interface. +#include "compiler/preprocessor/preprocess.h" + +#define SETUP_CONTEXT(pp) \ + TParseContext* context = (TParseContext*) pp->pC; \ + struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; + +// Preprocessor callbacks. +void CPPDebugLogMsg(const char *msg) +{ + SETUP_CONTEXT(cpp); + context->infoSink.debug.message(EPrefixNone, msg); +} + +void CPPWarningToInfoLog(const char *msg) +{ + SETUP_CONTEXT(cpp); + context->warning(yylineno, msg, "", ""); +} + +void CPPShInfoLogMsg(const char *msg) +{ + SETUP_CONTEXT(cpp); + context->error(yylineno, msg, "", ""); + context->recover(); +} + +void CPPErrorToInfoLog(char *msg) +{ + SETUP_CONTEXT(cpp); + context->error(yylineno, msg, "", ""); + context->recover(); +} + +void SetLineNumber(int line) +{ + SETUP_CONTEXT(cpp); + int string = 0; + DecodeSourceLoc(yylineno, &string, NULL); + yylineno = EncodeSourceLoc(string, line); +} + +void SetStringNumber(int string) +{ + SETUP_CONTEXT(cpp); + int line = 0; + DecodeSourceLoc(yylineno, NULL, &line); + yylineno = EncodeSourceLoc(string, line); +} + +int GetStringNumber() +{ + SETUP_CONTEXT(cpp); + int string = 0; + DecodeSourceLoc(yylineno, &string, NULL); + return string; +} + +int GetLineNumber() +{ + SETUP_CONTEXT(cpp); + int line = 0; + DecodeSourceLoc(yylineno, NULL, &line); + return line; +} + +void IncLineNumber() +{ + SETUP_CONTEXT(cpp); + int string = 0, line = 0; + DecodeSourceLoc(yylineno, &string, &line); + yylineno = EncodeSourceLoc(string, ++line); +} + +void DecLineNumber() +{ + SETUP_CONTEXT(cpp); + int string = 0, line = 0; + DecodeSourceLoc(yylineno, &string, &line); + yylineno = EncodeSourceLoc(string, --line); +} + +void HandlePragma(const char **tokens, int numTokens) +{ + SETUP_CONTEXT(cpp); + if (!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")) + context->contextPragma.optimize = true; + else if (!strcmp(tokens[2], "off")) + context->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")) + context->contextPragma.debug = true; + else if (!strcmp(tokens[2], "off")) + context->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) +{ + SETUP_CONTEXT(cpp); + TString strSrc; + strSrc = TString(string); + + context->HashErrMsg = context->HashErrMsg + " " + strSrc; +} + +const char* GetStrfromTStr(void) +{ + SETUP_CONTEXT(cpp); + cpp->ErrMsg = context->HashErrMsg.c_str(); + return cpp->ErrMsg; +} + +void ResetTString(void) +{ + SETUP_CONTEXT(cpp); + context->HashErrMsg = ""; +} + +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) +{ + SETUP_CONTEXT(cpp); + 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 = context->extensionBehavior.begin(); iter != context->extensionBehavior.end(); ++iter) + iter->second = behaviorVal; + } + } else { + iter = context->extensionBehavior.find(TString(extName)); + if (iter == context->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"; + context->infoSink.info.message(EPrefixWarning, msg.c_str(), yylineno); + break; + } + return; + } else + iter->second = behaviorVal; + } +} +} // extern "C" + +int string_input(char* buf, int max_size, yyscan_t yyscanner) { + 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; +} + +int check_type(yyscan_t yyscanner) { + struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; + + int token = IDENTIFIER; + TSymbol* symbol = yyextra->symbolTable.find(yytext); + if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) { + TVariable* variable = static_cast<TVariable*>(symbol); + if (variable->isUserType()) { + yyextra->lexAfterType = true; + token = TYPE_NAME; + } + } + yylval->lex.symbol = symbol; + return token; +} + +int reserved_word(yyscan_t yyscanner) { + struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; + + yyextra->error(yylineno, "Illegal use of reserved word", yytext, ""); + yyextra->recover(); + return 0; +} + +void yyerror(TParseContext* context, const char* reason) { + struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; + + if (context->AfterEOF) { + context->error(yylineno, reason, "unexpected EOF", ""); + } else { + context->error(yylineno, reason, yytext, ""); + } + context->recover(); +} + +int glslang_initialize(TParseContext* context) { + yyscan_t scanner = NULL; + if (yylex_init_extra(context, &scanner)) + return 1; + + context->scanner = scanner; + return 0; +} + +int glslang_finalize(TParseContext* context) { + yyscan_t scanner = context->scanner; + if (scanner == NULL) return 0; + + context->scanner = NULL; + return yylex_destroy(scanner); +} + +void glslang_scan(int count, const char* const string[], const int length[], + TParseContext* context) { + yyrestart(NULL, context->scanner); + yyset_lineno(EncodeSourceLoc(0, 1), context->scanner); + context->AfterEOF = false; + + // Init preprocessor. + cpp->pC = context; + cpp->PaWhichStr = 0; + cpp->PaArgv = string; + cpp->PaArgc = count; + cpp->PaStrLen = length; + cpp->pastFirstStatement = 0; + ScanFromString(string[0]); +} + diff --git a/Source/ThirdParty/ANGLE/src/compiler/glslang.y b/Source/ThirdParty/ANGLE/src/compiler/glslang.y new file mode 100644 index 000000000..d05f44195 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/glslang.y @@ -0,0 +1,2072 @@ +/* +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +This file contains the Yacc grammar for GLSL ES. +Based on ANSI C Yacc grammar: +http://www.lysator.liu.se/c/ANSI-C-grammar-y.html + +IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_glslang_parser.sh, +WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). +*/ + +%{ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// This file is auto-generated by generate_glslang_parser.sh. DO NOT EDIT! + +#include "compiler/SymbolTable.h" +#include "compiler/ParseHelper.h" +#include "GLSLANG/ShaderLang.h" + +#define YYLEX_PARAM context->scanner +%} + +%expect 1 /* One shift reduce conflict because of if | else */ +%pure-parser +%parse-param {TParseContext* context} + +%union { + struct { + TSourceLoc line; + union { + TString *string; + float f; + int i; + bool b; + }; + TSymbol* symbol; + } lex; + struct { + TSourceLoc line; + TOperator op; + union { + TIntermNode* intermNode; + TIntermNodePair nodePair; + TIntermTyped* intermTypedNode; + TIntermAggregate* intermAggregate; + }; + union { + TPublicType type; + TPrecision precision; + TQualifier qualifier; + TFunction* function; + TParameter param; + TTypeLine typeLine; + TTypeList* typeList; + }; + } interm; +} + +%{ +extern int yylex(YYSTYPE* yylval_param, void* yyscanner); +extern void yyerror(TParseContext* context, const char* reason); + +#define FRAG_VERT_ONLY(S, L) { \ + if (context->shaderType != SH_FRAGMENT_SHADER && \ + context->shaderType != SH_VERTEX_SHADER) { \ + context->error(L, " supported in vertex/fragment shaders only ", S, "", ""); \ + context->recover(); \ + } \ +} + +#define VERTEX_ONLY(S, L) { \ + if (context->shaderType != SH_VERTEX_SHADER) { \ + context->error(L, " supported in vertex shaders only ", S, "", ""); \ + context->recover(); \ + } \ +} + +#define FRAG_ONLY(S, L) { \ + if (context->shaderType != SH_FRAGMENT_SHADER) { \ + context->error(L, " supported in fragment shaders only ", S, "", ""); \ + context->recover(); \ + } \ +} +%} + +%token <lex> INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION +%token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE +%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN +%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4 +%token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING +%token <lex> STRUCT VOID_TYPE WHILE +%token <lex> SAMPLER2D SAMPLERCUBE + +%token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT +%token <lex> FIELD_SELECTION +%token <lex> LEFT_OP RIGHT_OP +%token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP +%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN +%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN +%token <lex> SUB_ASSIGN + +%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT +%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT +%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION + +%type <interm> assignment_operator unary_operator +%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression +%type <interm.intermTypedNode> expression integer_expression assignment_expression +%type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression +%type <interm.intermTypedNode> relational_expression equality_expression +%type <interm.intermTypedNode> conditional_expression constant_expression +%type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression +%type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression +%type <interm.intermTypedNode> function_call initializer condition conditionopt + +%type <interm.intermNode> translation_unit function_definition +%type <interm.intermNode> statement simple_statement +%type <interm.intermAggregate> statement_list compound_statement +%type <interm.intermNode> declaration_statement selection_statement expression_statement +%type <interm.intermNode> declaration external_declaration +%type <interm.intermNode> for_init_statement compound_statement_no_new_scope +%type <interm.nodePair> selection_rest_statement for_rest_statement +%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope +%type <interm> single_declaration init_declarator_list + +%type <interm> parameter_declaration parameter_declarator parameter_type_specifier +%type <interm.qualifier> parameter_qualifier + +%type <interm.precision> precision_qualifier +%type <interm.type> type_qualifier fully_specified_type type_specifier +%type <interm.type> type_specifier_no_prec type_specifier_nonarray +%type <interm.type> struct_specifier +%type <interm.typeLine> struct_declarator +%type <interm.typeList> struct_declarator_list struct_declaration struct_declaration_list +%type <interm.function> function_header function_declarator function_identifier +%type <interm.function> function_header_with_parameters function_call_header +%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype +%type <interm> function_call_or_method + +%start translation_unit +%% + +variable_identifier + : IDENTIFIER { + // The symbol table search was done in the lexical phase + const TSymbol* symbol = $1.symbol; + const TVariable* variable; + if (symbol == 0) { + context->error($1.line, "undeclared identifier", $1.string->c_str(), ""); + context->recover(); + TType type(EbtFloat, EbpUndefined); + TVariable* fakeVariable = new TVariable($1.string, type); + context->symbolTable.insert(*fakeVariable); + variable = fakeVariable; + } else { + // This identifier can only be a variable type symbol + if (! symbol->isVariable()) { + context->error($1.line, "variable expected", $1.string->c_str(), ""); + context->recover(); + } + variable = static_cast<const TVariable*>(symbol); + } + + // don't delete $1.string, it's used by error recovery, and the pool + // pop will reclaim the memory + + if (variable->getType().getQualifier() == EvqConst ) { + ConstantUnion* constArray = variable->getConstPointer(); + TType t(variable->getType()); + $$ = context->intermediate.addConstantUnion(constArray, t, $1.line); + } else + $$ = context->intermediate.addSymbol(variable->getUniqueId(), + variable->getName(), + variable->getType(), $1.line); + } + ; + +primary_expression + : variable_identifier { + $$ = $1; + } + | INTCONSTANT { + // + // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders, + // check for overflow for constants + // + if (abs($1.i) >= (1 << 16)) { + context->error($1.line, " integer constant overflow", "", ""); + context->recover(); + } + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst($1.i); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $1.line); + } + | FLOATCONSTANT { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setFConst($1.f); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line); + } + | BOOLCONSTANT { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst($1.b); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $1.line); + } + | LEFT_PAREN expression RIGHT_PAREN { + $$ = $2; + } + ; + +postfix_expression + : primary_expression { + $$ = $1; + } + | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET { + if (!$1->isArray() && !$1->isMatrix() && !$1->isVector()) { + if ($1->getAsSymbolNode()) + context->error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str(), ""); + else + context->error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression", ""); + context->recover(); + } + if ($1->getType().getQualifier() == EvqConst && $3->getQualifier() == EvqConst) { + if ($1->isArray()) { // constant folding for arrays + $$ = context->addConstArrayNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line); + } else if ($1->isVector()) { // constant folding for vectors + TVectorFields fields; + fields.num = 1; + fields.offsets[0] = $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(); // need to do it this way because v.xy sends fields integer array + $$ = context->addConstVectorNode(fields, $1, $2.line); + } else if ($1->isMatrix()) { // constant folding for matrices + $$ = context->addConstMatrixNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line); + } + } else { + if ($3->getQualifier() == EvqConst) { + if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() && !$1->isArray() ) { + context->error($2.line, "", "[", "field selection out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()); + context->recover(); + } else { + if ($1->isArray()) { + if ($1->getType().getArraySize() == 0) { + if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()) { + if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, $2.line)) + context->recover(); + } else { + if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line)) + context->recover(); + } + } else if ( $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= $1->getType().getArraySize()) { + context->error($2.line, "", "[", "array index out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()); + context->recover(); + } + } + $$ = context->intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line); + } + } else { + if ($1->isArray() && $1->getType().getArraySize() == 0) { + context->error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable"); + context->recover(); + } + + $$ = context->intermediate.addIndex(EOpIndexIndirect, $1, $3, $2.line); + } + } + if ($$ == 0) { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setFConst(0.0f); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), $2.line); + } else if ($1->isArray()) { + if ($1->getType().getStruct()) + $$->setType(TType($1->getType().getStruct(), $1->getType().getTypeName())); + else + $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize(), $1->isMatrix())); + + if ($1->getType().getQualifier() == EvqConst) + $$->getTypePointer()->setQualifier(EvqConst); + } else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConst) + $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, $1->getNominalSize())); + else if ($1->isMatrix()) + $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize())); + else if ($1->isVector() && $1->getType().getQualifier() == EvqConst) + $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst)); + else if ($1->isVector()) + $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary)); + else + $$->setType($1->getType()); + } + | function_call { + $$ = $1; + } + | postfix_expression DOT FIELD_SELECTION { + if ($1->isArray()) { + context->error($3.line, "cannot apply dot operator to an array", ".", ""); + context->recover(); + } + + if ($1->isVector()) { + TVectorFields fields; + if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, $3.line)) { + fields.num = 1; + fields.offsets[0] = 0; + context->recover(); + } + + if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields + $$ = context->addConstVectorNode(fields, $1, $3.line); + if ($$ == 0) { + context->recover(); + $$ = $1; + } + else + $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size())); + } else { + if (fields.num == 1) { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(fields.offsets[0]); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line); + $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line); + $$->setType(TType($1->getBasicType(), $1->getPrecision())); + } else { + TString vectorString = *$3.string; + TIntermTyped* index = context->intermediate.addSwizzle(fields, $3.line); + $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line); + $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size())); + } + } + } else if ($1->isMatrix()) { + TMatrixFields fields; + if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) { + fields.wholeRow = false; + fields.wholeCol = false; + fields.row = 0; + fields.col = 0; + context->recover(); + } + + if (fields.wholeRow || fields.wholeCol) { + context->error($2.line, " non-scalar fields not implemented yet", ".", ""); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(0); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line); + $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line); + $$->setType(TType($1->getBasicType(), $1->getPrecision(),EvqTemporary, $1->getNominalSize())); + } else { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line); + $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line); + $$->setType(TType($1->getBasicType(), $1->getPrecision())); + } + } else if ($1->getBasicType() == EbtStruct) { + bool fieldFound = false; + const TTypeList* fields = $1->getType().getStruct(); + if (fields == 0) { + context->error($2.line, "structure has no fields", "Internal Error", ""); + context->recover(); + $$ = $1; + } else { + unsigned int i; + for (i = 0; i < fields->size(); ++i) { + if ((*fields)[i].type->getFieldName() == *$3.string) { + fieldFound = true; + break; + } + } + if (fieldFound) { + if ($1->getType().getQualifier() == EvqConst) { + $$ = context->addConstStruct(*$3.string, $1, $2.line); + if ($$ == 0) { + context->recover(); + $$ = $1; + } + else { + $$->setType(*(*fields)[i].type); + // change the qualifier of the return type, not of the structure field + // as the structure definition is shared between various structures. + $$->getTypePointer()->setQualifier(EvqConst); + } + } else { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(i); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, $3.line); + $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, $2.line); + $$->setType(*(*fields)[i].type); + } + } else { + context->error($2.line, " no such field in structure", $3.string->c_str(), ""); + context->recover(); + $$ = $1; + } + } + } else { + context->error($2.line, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str(), ""); + context->recover(); + $$ = $1; + } + // don't delete $3.string, it's from the pool + } + | postfix_expression INC_OP { + if (context->lValueErrorCheck($2.line, "++", $1)) + context->recover(); + $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line, context->symbolTable); + if ($$ == 0) { + context->unaryOpError($2.line, "++", $1->getCompleteString()); + context->recover(); + $$ = $1; + } + } + | postfix_expression DEC_OP { + if (context->lValueErrorCheck($2.line, "--", $1)) + context->recover(); + $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line, context->symbolTable); + if ($$ == 0) { + context->unaryOpError($2.line, "--", $1->getCompleteString()); + context->recover(); + $$ = $1; + } + } + ; + +integer_expression + : expression { + if (context->integerErrorCheck($1, "[]")) + context->recover(); + $$ = $1; + } + ; + +function_call + : function_call_or_method { + TFunction* fnCall = $1.function; + TOperator op = fnCall->getBuiltInOp(); + + if (op != EOpNull) + { + // + // Then this should be a constructor. + // Don't go through the symbol table for constructors. + // Their parameters will be verified algorithmically. + // + TType type(EbtVoid, EbpUndefined); // use this to get the type back + if (context->constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) { + $$ = 0; + } else { + // + // It's a constructor, of type 'type'. + // + $$ = context->addConstructor($1.intermNode, &type, op, fnCall, $1.line); + } + + if ($$ == 0) { + context->recover(); + $$ = context->intermediate.setAggregateOperator(0, op, $1.line); + } + $$->setType(type); + } else { + // + // Not a constructor. Find it in the symbol table. + // + const TFunction* fnCandidate; + bool builtIn; + fnCandidate = context->findFunction($1.line, fnCall, &builtIn); + if (fnCandidate) { + // + // A declared function. + // + if (builtIn && !fnCandidate->getExtension().empty() && + context->extensionErrorCheck($1.line, fnCandidate->getExtension())) { + context->recover(); + } + op = fnCandidate->getBuiltInOp(); + if (builtIn && op != EOpNull) { + // + // A function call mapped to a built-in operation. + // + if (fnCandidate->getParamCount() == 1) { + // + // Treat it like a built-in unary operator. + // + $$ = context->intermediate.addUnaryMath(op, $1.intermNode, 0, context->symbolTable); + if ($$ == 0) { + context->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 { + $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, $1.line); + } + } else { + // This is a real function call + + $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, $1.line); + $$->setType(fnCandidate->getReturnType()); + + // this is how we know whether the given function is a builtIn function or a user defined function + // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also + // if builtIn == true, it's definitely a builtIn function with EOpNull + if (!builtIn) + $$->getAsAggregate()->setUserDefined(); + $$->getAsAggregate()->setName(fnCandidate->getMangledName()); + + TQualifier qual; + for (int i = 0; i < fnCandidate->getParamCount(); ++i) { + qual = fnCandidate->getParam(i).type->getQualifier(); + if (qual == EvqOut || qual == EvqInOut) { + if (context->lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) { + context->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", ""); + context->recover(); + } + } + } + } + $$->setType(fnCandidate->getReturnType()); + } else { + // error message was put out by PaFindFunction() + // Put on a dummy node for error recovery + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setFConst(0.0f); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line); + context->recover(); + } + } + delete fnCall; + } + ; + +function_call_or_method + : function_call_generic { + $$ = $1; + } + | postfix_expression DOT function_call_generic { + context->error($3.line, "methods are not supported", "", ""); + context->recover(); + $$ = $3; + } + ; + +function_call_generic + : function_call_header_with_parameters RIGHT_PAREN { + $$ = $1; + $$.line = $2.line; + } + | function_call_header_no_parameters RIGHT_PAREN { + $$ = $1; + $$.line = $2.line; + } + ; + +function_call_header_no_parameters + : function_call_header VOID_TYPE { + $$.function = $1; + $$.intermNode = 0; + } + | function_call_header { + $$.function = $1; + $$.intermNode = 0; + } + ; + +function_call_header_with_parameters + : function_call_header assignment_expression { + TParameter param = { 0, new TType($2->getType()) }; + $1->addParameter(param); + $$.function = $1; + $$.intermNode = $2; + } + | function_call_header_with_parameters COMMA assignment_expression { + TParameter param = { 0, new TType($3->getType()) }; + $1.function->addParameter(param); + $$.function = $1.function; + $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, $2.line); + } + ; + +function_call_header + : function_identifier LEFT_PAREN { + $$ = $1; + } + ; + +// Grammar Note: Constructors look like functions, but are recognized as types. + +function_identifier + : type_specifier_nonarray { + // + // Constructor + // + TOperator op = EOpNull; + if ($1.userDef) { + op = EOpConstructStruct; + } else { + switch ($1.type) { + case EbtFloat: + if ($1.matrix) { + switch($1.size) { + case 2: op = EOpConstructMat2; break; + case 3: op = EOpConstructMat3; break; + case 4: op = EOpConstructMat4; break; + } + } else { + switch($1.size) { + case 1: op = EOpConstructFloat; break; + case 2: op = EOpConstructVec2; break; + case 3: op = EOpConstructVec3; break; + case 4: op = EOpConstructVec4; break; + } + } + break; + case EbtInt: + switch($1.size) { + case 1: op = EOpConstructInt; break; + case 2: FRAG_VERT_ONLY("ivec2", $1.line); op = EOpConstructIVec2; break; + case 3: FRAG_VERT_ONLY("ivec3", $1.line); op = EOpConstructIVec3; break; + case 4: FRAG_VERT_ONLY("ivec4", $1.line); op = EOpConstructIVec4; break; + } + break; + case EbtBool: + switch($1.size) { + case 1: op = EOpConstructBool; break; + case 2: FRAG_VERT_ONLY("bvec2", $1.line); op = EOpConstructBVec2; break; + case 3: FRAG_VERT_ONLY("bvec3", $1.line); op = EOpConstructBVec3; break; + case 4: FRAG_VERT_ONLY("bvec4", $1.line); op = EOpConstructBVec4; break; + } + break; + default: break; + } + if (op == EOpNull) { + context->error($1.line, "cannot construct this type", getBasicString($1.type), ""); + context->recover(); + $1.type = EbtFloat; + op = EOpConstructFloat; + } + } + TString tempString; + TType type($1); + TFunction *function = new TFunction(&tempString, type, op); + $$ = function; + } + | IDENTIFIER { + if (context->reservedErrorCheck($1.line, *$1.string)) + context->recover(); + TType type(EbtVoid, EbpUndefined); + TFunction *function = new TFunction($1.string, type); + $$ = function; + } + | FIELD_SELECTION { + if (context->reservedErrorCheck($1.line, *$1.string)) + context->recover(); + TType type(EbtVoid, EbpUndefined); + TFunction *function = new TFunction($1.string, type); + $$ = function; + } + ; + +unary_expression + : postfix_expression { + $$ = $1; + } + | INC_OP unary_expression { + if (context->lValueErrorCheck($1.line, "++", $2)) + context->recover(); + $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line, context->symbolTable); + if ($$ == 0) { + context->unaryOpError($1.line, "++", $2->getCompleteString()); + context->recover(); + $$ = $2; + } + } + | DEC_OP unary_expression { + if (context->lValueErrorCheck($1.line, "--", $2)) + context->recover(); + $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line, context->symbolTable); + if ($$ == 0) { + context->unaryOpError($1.line, "--", $2->getCompleteString()); + context->recover(); + $$ = $2; + } + } + | unary_operator unary_expression { + if ($1.op != EOpNull) { + $$ = context->intermediate.addUnaryMath($1.op, $2, $1.line, context->symbolTable); + if ($$ == 0) { + const char* errorOp = ""; + switch($1.op) { + case EOpNegative: errorOp = "-"; break; + case EOpLogicalNot: errorOp = "!"; break; + default: break; + } + context->unaryOpError($1.line, errorOp, $2->getCompleteString()); + context->recover(); + $$ = $2; + } + } else + $$ = $2; + } + ; +// Grammar Note: No traditional style type casts. + +unary_operator + : PLUS { $$.line = $1.line; $$.op = EOpNull; } + | DASH { $$.line = $1.line; $$.op = EOpNegative; } + | BANG { $$.line = $1.line; $$.op = EOpLogicalNot; } + ; +// Grammar Note: No '*' or '&' unary ops. Pointers are not supported. + +multiplicative_expression + : unary_expression { $$ = $1; } + | multiplicative_expression STAR unary_expression { + FRAG_VERT_ONLY("*", $2.line); + $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, $2.line, context->symbolTable); + if ($$ == 0) { + context->binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + $$ = $1; + } + } + | multiplicative_expression SLASH unary_expression { + FRAG_VERT_ONLY("/", $2.line); + $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, context->symbolTable); + if ($$ == 0) { + context->binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + $$ = $1; + } + } + ; + +additive_expression + : multiplicative_expression { $$ = $1; } + | additive_expression PLUS multiplicative_expression { + $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, context->symbolTable); + if ($$ == 0) { + context->binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + $$ = $1; + } + } + | additive_expression DASH multiplicative_expression { + $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, context->symbolTable); + if ($$ == 0) { + context->binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + $$ = $1; + } + } + ; + +shift_expression + : additive_expression { $$ = $1; } + ; + +relational_expression + : shift_expression { $$ = $1; } + | relational_expression LEFT_ANGLE shift_expression { + $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line, context->symbolTable); + if ($$ == 0) { + context->binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + } + } + | relational_expression RIGHT_ANGLE shift_expression { + $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, context->symbolTable); + if ($$ == 0) { + context->binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + } + } + | relational_expression LE_OP shift_expression { + $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, context->symbolTable); + if ($$ == 0) { + context->binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + } + } + | relational_expression GE_OP shift_expression { + $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, context->symbolTable); + if ($$ == 0) { + context->binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + } + } + ; + +equality_expression + : relational_expression { $$ = $1; } + | equality_expression EQ_OP relational_expression { + $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, context->symbolTable); + if ($$ == 0) { + context->binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + } + } + | equality_expression NE_OP relational_expression { + $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, context->symbolTable); + if ($$ == 0) { + context->binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + } + } + ; + +and_expression + : equality_expression { $$ = $1; } + ; + +exclusive_or_expression + : and_expression { $$ = $1; } + ; + +inclusive_or_expression + : exclusive_or_expression { $$ = $1; } + ; + +logical_and_expression + : inclusive_or_expression { $$ = $1; } + | logical_and_expression AND_OP inclusive_or_expression { + $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line, context->symbolTable); + if ($$ == 0) { + context->binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + } + } + ; + +logical_xor_expression + : logical_and_expression { $$ = $1; } + | logical_xor_expression XOR_OP logical_and_expression { + $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line, context->symbolTable); + if ($$ == 0) { + context->binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + } + } + ; + +logical_or_expression + : logical_xor_expression { $$ = $1; } + | logical_or_expression OR_OP logical_xor_expression { + $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line, context->symbolTable); + if ($$ == 0) { + context->binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + } + } + ; + +conditional_expression + : logical_or_expression { $$ = $1; } + | logical_or_expression QUESTION expression COLON assignment_expression { + if (context->boolErrorCheck($2.line, $1)) + context->recover(); + + $$ = context->intermediate.addSelection($1, $3, $5, $2.line); + if ($3->getType() != $5->getType()) + $$ = 0; + + if ($$ == 0) { + context->binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString()); + context->recover(); + $$ = $5; + } + } + ; + +assignment_expression + : conditional_expression { $$ = $1; } + | unary_expression assignment_operator assignment_expression { + if (context->lValueErrorCheck($2.line, "assign", $1)) + context->recover(); + $$ = context->intermediate.addAssign($2.op, $1, $3, $2.line); + if ($$ == 0) { + context->assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + $$ = $1; + } + } + ; + +assignment_operator + : EQUAL { $$.line = $1.line; $$.op = EOpAssign; } + | MUL_ASSIGN { FRAG_VERT_ONLY("*=", $1.line); $$.line = $1.line; $$.op = EOpMulAssign; } + | DIV_ASSIGN { FRAG_VERT_ONLY("/=", $1.line); $$.line = $1.line; $$.op = EOpDivAssign; } + | ADD_ASSIGN { $$.line = $1.line; $$.op = EOpAddAssign; } + | SUB_ASSIGN { $$.line = $1.line; $$.op = EOpSubAssign; } + ; + +expression + : assignment_expression { + $$ = $1; + } + | expression COMMA assignment_expression { + $$ = context->intermediate.addComma($1, $3, $2.line); + if ($$ == 0) { + context->binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + $$ = $3; + } + } + ; + +constant_expression + : conditional_expression { + if (context->constErrorCheck($1)) + context->recover(); + $$ = $1; + } + ; + +declaration + : function_prototype SEMICOLON { + TFunction &function = *($1.function); + + TIntermAggregate *prototype = new TIntermAggregate; + prototype->setType(function.getReturnType()); + prototype->setName(function.getName()); + + for (int i = 0; i < function.getParamCount(); i++) + { + const TParameter ¶m = function.getParam(i); + if (param.name != 0) + { + TVariable *variable = new TVariable(param.name, *param.type); + + prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), $1.line), $1.line); + } + else + { + prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line); + } + } + + prototype->setOp(EOpPrototype); + $$ = prototype; + } + | init_declarator_list SEMICOLON { + if ($1.intermAggregate) + $1.intermAggregate->setOp(EOpDeclaration); + $$ = $1.intermAggregate; + } + | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON { + context->symbolTable.setDefaultPrecision( $3.type, $2 ); + $$ = 0; + } + ; + +function_prototype + : function_declarator RIGHT_PAREN { + // + // Multiple declarations of the same function are allowed. + // + // If this is a definition, the definition production code will check for redefinitions + // (we don't know at this point if it's a definition or not). + // + // Redeclarations are allowed. But, return types and parameter qualifiers must match. + // + TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find($1->getMangledName())); + if (prevDec) { + if (prevDec->getReturnType() != $1->getReturnType()) { + context->error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString(), ""); + context->recover(); + } + for (int i = 0; i < prevDec->getParamCount(); ++i) { + if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) { + context->error($2.line, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString(), ""); + context->recover(); + } + } + } + + // + // If this is a redeclaration, it could also be a definition, + // in which case, we want to use the variable names from this one, and not the one that's + // being redeclared. So, pass back up this declaration, not the one in the symbol table. + // + $$.function = $1; + $$.line = $2.line; + + context->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 + // + context->error($2.line, "cannot be an argument type except for '(void)'", "void", ""); + context->recover(); + delete $3.param.type; + } else { + // Add the parameter + $$ = $1; + $1->addParameter($3.param); + } + } + ; + +function_header + : fully_specified_type IDENTIFIER LEFT_PAREN { + if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) { + context->error($2.line, "no qualifiers allowed for function return", getQualifierString($1.qualifier), ""); + context->recover(); + } + // make sure a sampler is not involved as well... + if (context->structQualifierErrorCheck($2.line, $1)) + context->recover(); + + // Add the function as a prototype after parsing it (we do not support recursion) + TFunction *function; + TType type($1); + function = new TFunction($2.string, type); + $$ = function; + } + ; + +parameter_declarator + // Type + name + : type_specifier IDENTIFIER { + if ($1.type == EbtVoid) { + context->error($2.line, "illegal use of type 'void'", $2.string->c_str(), ""); + context->recover(); + } + if (context->reservedErrorCheck($2.line, *$2.string)) + context->recover(); + TParameter param = {$2.string, new TType($1)}; + $$.line = $2.line; + $$.param = param; + } + | type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { + // Check that we can make an array out of this type + if (context->arrayTypeErrorCheck($3.line, $1)) + context->recover(); + + if (context->reservedErrorCheck($2.line, *$2.string)) + context->recover(); + + int size; + if (context->arraySizeErrorCheck($3.line, $4, size)) + context->recover(); + $1.setArray(true, size); + + TType* type = new TType($1); + TParameter param = { $2.string, type }; + $$.line = $2.line; + $$.param = param; + } + ; + +parameter_declaration + // + // The only parameter qualifier a parameter can have are + // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST. + // + + // + // Type + name + // + : type_qualifier parameter_qualifier parameter_declarator { + $$ = $3; + if (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type)) + context->recover(); + } + | parameter_qualifier parameter_declarator { + $$ = $2; + if (context->parameterSamplerErrorCheck($2.line, $1, *$2.param.type)) + context->recover(); + if (context->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type)) + context->recover(); + } + // + // Only type + // + | type_qualifier parameter_qualifier parameter_type_specifier { + $$ = $3; + if (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type)) + context->recover(); + } + | parameter_qualifier parameter_type_specifier { + $$ = $2; + if (context->parameterSamplerErrorCheck($2.line, $1, *$2.param.type)) + context->recover(); + if (context->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type)) + context->recover(); + } + ; + +parameter_qualifier + : /* empty */ { + $$ = EvqIn; + } + | IN_QUAL { + $$ = EvqIn; + } + | OUT_QUAL { + $$ = EvqOut; + } + | INOUT_QUAL { + $$ = EvqInOut; + } + ; + +parameter_type_specifier + : type_specifier { + TParameter param = { 0, new TType($1) }; + $$.param = param; + } + ; + +init_declarator_list + : single_declaration { + $$ = $1; + } + | init_declarator_list COMMA IDENTIFIER { + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), $3.line); + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, $3.line); + + if (context->structQualifierErrorCheck($3.line, $$.type)) + context->recover(); + + if (context->nonInitConstErrorCheck($3.line, *$3.string, $$.type)) + context->recover(); + + TVariable* variable = 0; + if (context->nonInitErrorCheck($3.line, *$3.string, $$.type, variable)) + context->recover(); + if (symbol && variable) + symbol->setId(variable->getUniqueId()); + } + | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET { + if (context->structQualifierErrorCheck($3.line, $1.type)) + context->recover(); + + if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type)) + context->recover(); + + $$ = $1; + + if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type)) + context->recover(); + else { + $1.type.setArray(true); + TVariable* variable; + if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable)) + context->recover(); + } + } + | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { + if (context->structQualifierErrorCheck($3.line, $1.type)) + context->recover(); + + if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type)) + context->recover(); + + $$ = $1; + + if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type)) + context->recover(); + else { + int size; + if (context->arraySizeErrorCheck($4.line, $5, size)) + context->recover(); + $1.type.setArray(true, size); + TVariable* variable = 0; + if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable)) + context->recover(); + TType type = TType($1.type); + type.setArraySize(size); + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, $3.line), $3.line); + } + } + | init_declarator_list COMMA IDENTIFIER EQUAL initializer { + if (context->structQualifierErrorCheck($3.line, $1.type)) + context->recover(); + + $$ = $1; + + TIntermNode* intermNode; + if (!context->executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) { + // + // build the intermediate representation + // + if (intermNode) + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, $4.line); + else + $$.intermAggregate = $1.intermAggregate; + } else { + context->recover(); + $$.intermAggregate = 0; + } + } + ; + +single_declaration + : fully_specified_type { + $$.type = $1; + $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), $1.line), $1.line); + } + | fully_specified_type IDENTIFIER { + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line); + + if (context->structQualifierErrorCheck($2.line, $$.type)) + context->recover(); + + if (context->nonInitConstErrorCheck($2.line, *$2.string, $$.type)) + context->recover(); + + $$.type = $1; + + TVariable* variable = 0; + if (context->nonInitErrorCheck($2.line, *$2.string, $$.type, variable)) + context->recover(); + if (variable && symbol) + symbol->setId(variable->getUniqueId()); + } + | fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET { + context->error($2.line, "unsized array declarations not supported", $2.string->c_str(), ""); + context->recover(); + + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line); + $$.type = $1; + } + | fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { + TType type = TType($1); + int size; + if (context->arraySizeErrorCheck($2.line, $4, size)) + context->recover(); + type.setArraySize(size); + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, $2.line); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line); + + if (context->structQualifierErrorCheck($2.line, $1)) + context->recover(); + + if (context->nonInitConstErrorCheck($2.line, *$2.string, $1)) + context->recover(); + + $$.type = $1; + + if (context->arrayTypeErrorCheck($3.line, $1) || context->arrayQualifierErrorCheck($3.line, $1)) + context->recover(); + else { + int size; + if (context->arraySizeErrorCheck($3.line, $4, size)) + context->recover(); + + $1.setArray(true, size); + TVariable* variable = 0; + if (context->arrayErrorCheck($3.line, *$2.string, $1, variable)) + context->recover(); + if (variable && symbol) + symbol->setId(variable->getUniqueId()); + } + } + | fully_specified_type IDENTIFIER EQUAL initializer { + if (context->structQualifierErrorCheck($2.line, $1)) + context->recover(); + + $$.type = $1; + + TIntermNode* intermNode; + if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) { + // + // Build intermediate representation + // + if(intermNode) + $$.intermAggregate = context->intermediate.makeAggregate(intermNode, $3.line); + else + $$.intermAggregate = 0; + } else { + context->recover(); + $$.intermAggregate = 0; + } + } + | INVARIANT IDENTIFIER { + VERTEX_ONLY("invariant declaration", $1.line); + $$.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 (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "input")) +// context->recover(); +// UNPACK_ONLY("input", $1.line); +// $$.qualifier = EvqInput; +// } +// | OUTPUT { +// if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "output")) +// context->recover(); +// PACK_ONLY("output", $1.line); +// $$.qualifier = EvqOutput; +// } +// ; + +// +// Place holder for the pack/unpack languages. +// +//buffer_declaration_list +// : buffer_declaration { +// } +// | buffer_declaration_list buffer_declaration { +// } +// ; + +// +// Input/output semantics: +// float must be 16 or 32 bits +// float alignment restrictions? +// check for only one input and only one output +// sum of bitfields has to be multiple of 32 +// + +// +// Place holder for the pack/unpack languages. +// +//buffer_declaration +// : type_specifier IDENTIFIER COLON constant_expression SEMICOLON { +// if (context->reservedErrorCheck($2.line, *$2.string, context)) +// context->recover(); +// $$.variable = new TVariable($2.string, $1); +// if (! context->symbolTable.insert(*$$.variable)) { +// context->error($2.line, "redefinition", $$.variable->getName().c_str(), ""); +// context->recover(); +// // don't have to delete $$.variable, the pool pop will take care of it +// } +// } +// ; + +fully_specified_type + : type_specifier { + $$ = $1; + + if ($1.array) { + context->error($1.line, "not supported", "first-class array", ""); + context->recover(); + $1.setArray(false); + } + } + | type_qualifier type_specifier { + if ($2.array) { + context->error($2.line, "not supported", "first-class array", ""); + context->recover(); + $2.setArray(false); + } + + if ($1.qualifier == EvqAttribute && + ($2.type == EbtBool || $2.type == EbtInt)) { + context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), ""); + context->recover(); + } + if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) && + ($2.type == EbtBool || $2.type == EbtInt)) { + context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), ""); + context->recover(); + } + $$ = $2; + $$.qualifier = $1.qualifier; + } + ; + +type_qualifier + : CONST_QUAL { + $$.setBasic(EbtVoid, EvqConst, $1.line); + } + | ATTRIBUTE { + VERTEX_ONLY("attribute", $1.line); + if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "attribute")) + context->recover(); + $$.setBasic(EbtVoid, EvqAttribute, $1.line); + } + | VARYING { + if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "varying")) + context->recover(); + if (context->shaderType == SH_VERTEX_SHADER) + $$.setBasic(EbtVoid, EvqVaryingOut, $1.line); + else + $$.setBasic(EbtVoid, EvqVaryingIn, $1.line); + } + | INVARIANT VARYING { + if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "invariant varying")) + context->recover(); + if (context->shaderType == SH_VERTEX_SHADER) + $$.setBasic(EbtVoid, EvqInvariantVaryingOut, $1.line); + else + $$.setBasic(EbtVoid, EvqInvariantVaryingIn, $1.line); + } + | UNIFORM { + if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "uniform")) + context->recover(); + $$.setBasic(EbtVoid, EvqUniform, $1.line); + } + ; + +type_specifier + : type_specifier_no_prec { + $$ = $1; + + if ($$.precision == EbpUndefined) { + $$.precision = context->symbolTable.getDefaultPrecision($1.type); + if (context->precisionErrorCheck($1.line, $$.precision, $1.type)) { + context->recover(); + } + } + } + | precision_qualifier type_specifier_no_prec { + $$ = $2; + $$.precision = $1; + } + ; + +precision_qualifier + : HIGH_PRECISION { + $$ = EbpHigh; + } + | MEDIUM_PRECISION { + $$ = EbpMedium; + } + | LOW_PRECISION { + $$ = EbpLow; + } + ; + +type_specifier_no_prec + : type_specifier_nonarray { + $$ = $1; + } + | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET { + $$ = $1; + + if (context->arrayTypeErrorCheck($2.line, $1)) + context->recover(); + else { + int size; + if (context->arraySizeErrorCheck($2.line, $3, size)) + context->recover(); + $$.setArray(true, size); + } + } + ; + +type_specifier_nonarray + : VOID_TYPE { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtVoid, qual, $1.line); + } + | FLOAT_TYPE { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, $1.line); + } + | INT_TYPE { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtInt, qual, $1.line); + } + | BOOL_TYPE { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtBool, qual, $1.line); + } +// | UNSIGNED INT_TYPE { +// PACK_UNPACK_ONLY("unsigned", $1.line); +// TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; +// $$.setBasic(EbtInt, qual, $1.line); +// } + | VEC2 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, $1.line); + $$.setAggregate(2); + } + | VEC3 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, $1.line); + $$.setAggregate(3); + } + | VEC4 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, $1.line); + $$.setAggregate(4); + } + | BVEC2 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtBool, qual, $1.line); + $$.setAggregate(2); + } + | BVEC3 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtBool, qual, $1.line); + $$.setAggregate(3); + } + | BVEC4 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtBool, qual, $1.line); + $$.setAggregate(4); + } + | IVEC2 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtInt, qual, $1.line); + $$.setAggregate(2); + } + | IVEC3 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtInt, qual, $1.line); + $$.setAggregate(3); + } + | IVEC4 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtInt, qual, $1.line); + $$.setAggregate(4); + } + | MATRIX2 { + FRAG_VERT_ONLY("mat2", $1.line); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, $1.line); + $$.setAggregate(2, true); + } + | MATRIX3 { + FRAG_VERT_ONLY("mat3", $1.line); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, $1.line); + $$.setAggregate(3, true); + } + | MATRIX4 { + FRAG_VERT_ONLY("mat4", $1.line); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, $1.line); + $$.setAggregate(4, true); + } + | SAMPLER2D { + FRAG_VERT_ONLY("sampler2D", $1.line); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler2D, qual, $1.line); + } + | SAMPLERCUBE { + FRAG_VERT_ONLY("samplerCube", $1.line); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSamplerCube, qual, $1.line); + } + | struct_specifier { + FRAG_VERT_ONLY("struct", $1.line); + $$ = $1; + $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + } + | TYPE_NAME { + // + // This is for user defined type names. The lexical phase looked up the + // type. + // + TType& structure = static_cast<TVariable*>($1.symbol)->getType(); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtStruct, qual, $1.line); + $$.userDef = &structure; + } + ; + +struct_specifier + : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE { + if (context->reservedErrorCheck($2.line, *$2.string)) + context->recover(); + + TType* structure = new TType($4, *$2.string); + TVariable* userTypeDef = new TVariable($2.string, *structure, true); + if (! context->symbolTable.insert(*userTypeDef)) { + context->error($2.line, "redefinition", $2.string->c_str(), "struct"); + context->recover(); + } + $$.setBasic(EbtStruct, EvqTemporary, $1.line); + $$.userDef = structure; + } + | 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()) { + context->error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str()); + context->recover(); + } + } + $$->push_back((*$2)[i]); + } + } + ; + +struct_declaration + : type_specifier struct_declarator_list SEMICOLON { + $$ = $2; + + if (context->voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) { + context->recover(); + } + for (unsigned int i = 0; i < $$->size(); ++i) { + // + // Careful not to replace already known aspects of type, like array-ness + // + TType* type = (*$$)[i].type; + type->setBasicType($1.type); + type->setNominalSize($1.size); + type->setMatrix($1.matrix); + type->setPrecision($1.precision); + + // don't allow arrays of arrays + if (type->isArray()) { + if (context->arrayTypeErrorCheck($1.line, $1)) + context->recover(); + } + if ($1.array) + type->setArraySize($1.arraySize); + if ($1.userDef) { + type->setStruct($1.userDef->getStruct()); + type->setTypeName($1.userDef->getTypeName()); + } + } + } + ; + +struct_declarator_list + : struct_declarator { + $$ = NewPoolTTypeList(); + $$->push_back($1); + } + | struct_declarator_list COMMA struct_declarator { + $$->push_back($3); + } + ; + +struct_declarator + : IDENTIFIER { + if (context->reservedErrorCheck($1.line, *$1.string)) + context->recover(); + + $$.type = new TType(EbtVoid, EbpUndefined); + $$.line = $1.line; + $$.type->setFieldName(*$1.string); + } + | IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { + if (context->reservedErrorCheck($1.line, *$1.string)) + context->recover(); + + $$.type = new TType(EbtVoid, EbpUndefined); + $$.line = $1.line; + $$.type->setFieldName(*$1.string); + + int size; + if (context->arraySizeErrorCheck($2.line, $3, size)) + context->recover(); + $$.type->setArraySize(size); + } + ; + +initializer + : assignment_expression { $$ = $1; } + ; + +declaration_statement + : declaration { $$ = $1; } + ; + +statement + : compound_statement { $$ = $1; } + | simple_statement { $$ = $1; } + ; + +// Grammar Note: No labeled statements; 'goto' is not supported. + +simple_statement + : declaration_statement { $$ = $1; } + | expression_statement { $$ = $1; } + | selection_statement { $$ = $1; } + | iteration_statement { $$ = $1; } + | jump_statement { $$ = $1; } + ; + +compound_statement + : LEFT_BRACE RIGHT_BRACE { $$ = 0; } + | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE { + if ($3 != 0) { + $3->setOp(EOpSequence); + $3->setEndLine($5.line); + } + $$ = $3; + } + ; + +statement_no_new_scope + : compound_statement_no_new_scope { $$ = $1; } + | simple_statement { $$ = $1; } + ; + +compound_statement_no_new_scope + // Statement that doesn't create a new scope, for selection_statement, iteration_statement + : LEFT_BRACE RIGHT_BRACE { + $$ = 0; + } + | LEFT_BRACE statement_list RIGHT_BRACE { + if ($2) { + $2->setOp(EOpSequence); + $2->setEndLine($3.line); + } + $$ = $2; + } + ; + +statement_list + : statement { + $$ = context->intermediate.makeAggregate($1, 0); + } + | statement_list statement { + $$ = context->intermediate.growAggregate($1, $2, 0); + } + ; + +expression_statement + : SEMICOLON { $$ = 0; } + | expression SEMICOLON { $$ = static_cast<TIntermNode*>($1); } + ; + +selection_statement + : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement { + if (context->boolErrorCheck($1.line, $3)) + context->recover(); + $$ = context->intermediate.addSelection($3, $5, $1.line); + } + ; + +selection_rest_statement + : statement 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 (context->boolErrorCheck($1->getLine(), $1)) + context->recover(); + } + | fully_specified_type IDENTIFIER EQUAL initializer { + TIntermNode* intermNode; + if (context->structQualifierErrorCheck($2.line, $1)) + context->recover(); + if (context->boolErrorCheck($2.line, $1)) + context->recover(); + + if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) + $$ = $4; + else { + context->recover(); + $$ = 0; + } + } + ; + +iteration_statement + : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope { + context->symbolTable.pop(); + $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, $1.line); + --context->loopNestingLevel; + } + | DO { ++context->loopNestingLevel; } statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { + if (context->boolErrorCheck($8.line, $6)) + context->recover(); + + $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, $4.line); + --context->loopNestingLevel; + } + | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { + context->symbolTable.pop(); + $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), $7, $1.line); + --context->loopNestingLevel; + } + ; + +for_init_statement + : expression_statement { + $$ = $1; + } + | declaration_statement { + $$ = $1; + } + ; + +conditionopt + : condition { + $$ = $1; + } + | /* May be null */ { + $$ = 0; + } + ; + +for_rest_statement + : conditionopt SEMICOLON { + $$.node1 = $1; + $$.node2 = 0; + } + | conditionopt SEMICOLON expression { + $$.node1 = $1; + $$.node2 = $3; + } + ; + +jump_statement + : CONTINUE SEMICOLON { + if (context->loopNestingLevel <= 0) { + context->error($1.line, "continue statement only allowed in loops", "", ""); + context->recover(); + } + $$ = context->intermediate.addBranch(EOpContinue, $1.line); + } + | BREAK SEMICOLON { + if (context->loopNestingLevel <= 0) { + context->error($1.line, "break statement only allowed in loops", "", ""); + context->recover(); + } + $$ = context->intermediate.addBranch(EOpBreak, $1.line); + } + | RETURN SEMICOLON { + $$ = context->intermediate.addBranch(EOpReturn, $1.line); + if (context->currentFunctionType->getBasicType() != EbtVoid) { + context->error($1.line, "non-void function must return a value", "return", ""); + context->recover(); + } + } + | RETURN expression SEMICOLON { + $$ = context->intermediate.addBranch(EOpReturn, $2, $1.line); + context->functionReturnsValue = true; + if (context->currentFunctionType->getBasicType() == EbtVoid) { + context->error($1.line, "void function cannot return a value", "return", ""); + context->recover(); + } else if (*(context->currentFunctionType) != $2->getType()) { + context->error($1.line, "function return is not matching type:", "return", ""); + context->recover(); + } + } + | DISCARD SEMICOLON { + FRAG_ONLY("discard", $1.line); + $$ = context->intermediate.addBranch(EOpKill, $1.line); + } + ; + +// Grammar Note: No 'goto'. Gotos are not supported. + +translation_unit + : external_declaration { + $$ = $1; + context->treeRoot = $$; + } + | translation_unit external_declaration { + $$ = context->intermediate.growAggregate($1, $2, 0); + context->treeRoot = $$; + } + ; + +external_declaration + : function_definition { + $$ = $1; + } + | declaration { + $$ = $1; + } + ; + +function_definition + : function_prototype { + TFunction* function = $1.function; + TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName())); + // + // Note: 'prevDec' could be 'function' if this is the first time we've seen function + // as it would have just been put in the symbol table. Otherwise, we're looking up + // an earlier occurance. + // + if (prevDec->isDefined()) { + // + // Then this function already has a body. + // + context->error($1.line, "function already has a body", function->getName().c_str(), ""); + context->recover(); + } + prevDec->setDefined(); + + // + // Raise error message if main function takes any parameters or return anything other than void + // + if (function->getName() == "main") { + if (function->getParamCount() > 0) { + context->error($1.line, "function cannot take any parameter(s)", function->getName().c_str(), ""); + context->recover(); + } + if (function->getReturnType().getBasicType() != EbtVoid) { + context->error($1.line, "", function->getReturnType().getBasicString(), "main function cannot return a value"); + context->recover(); + } + } + + // + // New symbol table scope for body of function plus its arguments + // + context->symbolTable.push(); + + // + // Remember the return type for later checking for RETURN statements. + // + context->currentFunctionType = &(prevDec->getReturnType()); + context->functionReturnsValue = false; + + // + // Insert parameters into the symbol table. + // If the parameter has no name, it's not an error, just don't insert it + // (could be used for unused args). + // + // Also, accumulate the list of parameters into the HIL, so lower level code + // knows where to find parameters. + // + TIntermAggregate* paramNodes = new TIntermAggregate; + for (int i = 0; i < function->getParamCount(); i++) { + const TParameter& param = function->getParam(i); + if (param.name != 0) { + TVariable *variable = new TVariable(param.name, *param.type); + // + // Insert the parameters with name in the symbol table. + // + if (! context->symbolTable.insert(*variable)) { + context->error($1.line, "redefinition", variable->getName().c_str(), ""); + context->recover(); + delete variable; + } + + // + // Add the parameter to the HIL + // + paramNodes = context->intermediate.growAggregate( + paramNodes, + context->intermediate.addSymbol(variable->getUniqueId(), + variable->getName(), + variable->getType(), $1.line), + $1.line); + } else { + paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line); + } + } + context->intermediate.setAggregateOperator(paramNodes, EOpParameters, $1.line); + $1.intermAggregate = paramNodes; + context->loopNestingLevel = 0; + } + compound_statement_no_new_scope { + //?? Check that all paths return a value if return type != void ? + // May be best done as post process phase on intermediate code + if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) { + context->error($1.line, "function does not return a value:", "", $1.function->getName().c_str()); + context->recover(); + } + context->symbolTable.pop(); + $$ = context->intermediate.growAggregate($1.intermAggregate, $3, 0); + context->intermediate.setAggregateOperator($$, EOpFunction, $1.line); + $$->getAsAggregate()->setName($1.function->getMangledName().c_str()); + $$->getAsAggregate()->setType($1.function->getReturnType()); + + // store the pragma information for debug and optimize and other vendor specific + // information. This information can be queried from the parse tree + $$->getAsAggregate()->setOptimize(context->contextPragma.optimize); + $$->getAsAggregate()->setDebug(context->contextPragma.debug); + $$->getAsAggregate()->addToPragmaTable(context->contextPragma.pragmaTable); + + if ($3 && $3->getAsAggregate()) + $$->getAsAggregate()->setEndLine($3->getAsAggregate()->getEndLine()); + } + ; + +%% + +int glslang_parse(TParseContext* context) { + return yyparse(context); +} + diff --git a/Source/ThirdParty/ANGLE/src/compiler/glslang_lex.cpp b/Source/ThirdParty/ANGLE/src/compiler/glslang_lex.cpp new file mode 100644 index 000000000..fa28d4162 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/glslang_lex.cpp @@ -0,0 +1,3190 @@ +#line 17 "compiler/glslang.l" +// +// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// This file is auto-generated by generate_glslang_lexer.sh. DO NOT EDIT! + + + +#line 13 "compiler/glslang_lex.cpp" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yyg->yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yyg->yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin ,yyscanner ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires + * access to the local variable yy_act. Since yyless() is a macro, it would break + * existing scanners that call yyless() from OUTSIDE yylex. + * One obvious solution it to make yy_act a global. I tried that, and saw + * a 5% performance hit in a non-yylineno scanner, because yy_act is + * normally declared as a register variable-- so it is not worth it. + */ + #define YY_LESS_LINENO(n) \ + do { \ + int yyl;\ + for ( yyl = n; yyl < yyleng; ++yyl )\ + if ( yytext[yyl] == '\n' )\ + --yylineno;\ + }while(0) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = yyg->yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ + ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] + +void yyrestart (FILE *input_file ,yyscan_t yyscanner ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void yypop_buffer_state (yyscan_t yyscanner ); + +static void yyensure_buffer_stack (yyscan_t yyscanner ); +static void yy_load_buffer_state (yyscan_t yyscanner ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); + +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner) + +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); + +void *yyalloc (yy_size_t ,yyscan_t yyscanner ); +void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +void yyfree (void * ,yyscan_t yyscanner ); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define yywrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +typedef int yy_state_type; + +#define yytext_ptr yytext_r + +static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); +static int yy_get_next_buffer (yyscan_t yyscanner ); +static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yyg->yytext_ptr = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + yyg->yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yyg->yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 145 +#define YY_END_OF_BUFFER 146 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[411] = + { 0, + 0, 0, 0, 0, 0, 0, 146, 144, 143, 143, + 128, 134, 139, 123, 124, 132, 131, 120, 129, 127, + 133, 92, 92, 121, 117, 135, 122, 136, 140, 88, + 125, 126, 138, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 118, 137, 119, 130, 3, 4, 3, + 142, 145, 141, 114, 100, 119, 108, 103, 98, 106, + 96, 107, 97, 95, 2, 1, 99, 94, 90, 91, + 0, 0, 92, 126, 118, 125, 115, 111, 113, 112, + 116, 88, 104, 110, 88, 88, 88, 88, 88, 88, + + 88, 88, 88, 88, 17, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 20, 22, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 105, 109, 5, 141, + 0, 1, 94, 0, 0, 93, 89, 101, 102, 48, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 18, 88, 88, + 88, 88, 88, 88, 88, 88, 26, 88, 88, 88, + 88, 88, 88, 88, 88, 23, 88, 88, 88, 88, + + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 0, 95, + 0, 94, 88, 28, 88, 88, 85, 88, 88, 88, + 88, 88, 88, 88, 21, 51, 88, 88, 88, 88, + 88, 56, 70, 88, 88, 88, 88, 88, 88, 88, + 88, 67, 9, 33, 34, 35, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 54, 29, 88, 88, 88, 88, 88, 88, 36, + 37, 38, 27, 88, 88, 88, 15, 42, 43, 44, + 49, 12, 88, 88, 88, 88, 81, 82, 83, 88, + + 30, 71, 25, 78, 79, 80, 7, 75, 76, 77, + 88, 24, 73, 88, 88, 39, 40, 41, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 68, 88, 88, + 88, 88, 88, 88, 88, 50, 88, 87, 88, 88, + 19, 88, 88, 88, 88, 69, 64, 59, 88, 88, + 88, 88, 88, 74, 55, 88, 62, 32, 88, 84, + 63, 47, 57, 88, 88, 88, 88, 88, 88, 88, + 88, 58, 31, 88, 88, 88, 8, 88, 88, 88, + 88, 88, 52, 13, 88, 14, 88, 88, 16, 65, + 88, 88, 88, 60, 88, 88, 88, 53, 72, 61, + + 11, 66, 6, 86, 10, 45, 88, 88, 46, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 1, 1, 1, 5, 6, 1, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 16, 16, 16, 20, 20, 21, 22, 23, + 24, 25, 26, 1, 27, 27, 28, 29, 30, 27, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 32, 31, 31, + 33, 1, 34, 35, 31, 1, 36, 37, 38, 39, + + 40, 41, 42, 43, 44, 31, 45, 46, 47, 48, + 49, 50, 31, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[64] = + { 0, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, + 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, + 4, 4, 1, 1, 1, 3, 3, 3, 3, 3, + 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, + 1, 1, 1 + } ; + +static yyconst flex_int16_t yy_base[416] = + { 0, + 0, 0, 61, 62, 71, 0, 606, 607, 607, 607, + 581, 42, 129, 607, 607, 580, 126, 607, 125, 123, + 137, 149, 157, 578, 607, 175, 578, 44, 607, 0, + 607, 607, 120, 95, 103, 142, 146, 136, 156, 552, + 168, 162, 551, 120, 158, 545, 173, 558, 172, 178, + 111, 186, 554, 607, 159, 607, 607, 607, 607, 582, + 607, 607, 0, 607, 607, 607, 607, 607, 607, 607, + 607, 607, 607, 222, 607, 0, 607, 228, 254, 262, + 281, 0, 290, 607, 607, 607, 571, 607, 607, 607, + 570, 0, 607, 607, 546, 539, 542, 550, 549, 536, + + 551, 538, 544, 532, 529, 542, 529, 526, 526, 532, + 520, 527, 524, 534, 520, 526, 529, 530, 0, 204, + 529, 207, 515, 528, 519, 521, 511, 525, 522, 524, + 507, 512, 509, 498, 183, 512, 508, 510, 499, 502, + 212, 507, 499, 511, 186, 504, 607, 607, 607, 0, + 306, 0, 316, 332, 270, 342, 0, 607, 607, 0, + 496, 500, 509, 506, 490, 490, 161, 505, 502, 502, + 500, 497, 489, 495, 482, 493, 496, 0, 493, 481, + 488, 485, 489, 482, 471, 470, 483, 486, 483, 478, + 469, 294, 474, 477, 468, 465, 469, 475, 466, 457, + + 460, 458, 468, 454, 452, 452, 454, 451, 462, 461, + 278, 456, 451, 440, 320, 458, 460, 449, 348, 354, + 360, 366, 450, 0, 448, 336, 0, 440, 438, 446, + 435, 452, 441, 370, 0, 0, 435, 445, 445, 430, + 373, 0, 0, 432, 376, 433, 427, 426, 427, 426, + 379, 0, 0, 0, 0, 0, 422, 423, 428, 419, + 432, 427, 426, 418, 422, 414, 417, 421, 426, 425, + 416, 0, 0, 422, 411, 411, 416, 415, 412, 0, + 0, 0, 0, 402, 414, 416, 0, 0, 0, 0, + 0, 0, 404, 405, 399, 409, 0, 0, 0, 400, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 407, 0, 0, 405, 401, 0, 0, 0, 397, 393, + 398, 388, 401, 387, 400, 389, 396, 0, 394, 396, + 380, 389, 395, 390, 378, 0, 380, 0, 379, 382, + 0, 371, 370, 370, 383, 0, 385, 0, 384, 383, + 368, 381, 368, 0, 0, 371, 0, 0, 363, 0, + 0, 0, 0, 360, 371, 364, 368, 303, 297, 288, + 300, 0, 0, 283, 290, 269, 0, 277, 274, 255, + 232, 255, 0, 0, 244, 0, 236, 226, 0, 0, + 225, 208, 211, 0, 185, 202, 131, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 134, 117, 0, 607, + 398, 400, 402, 406, 142 + } ; + +static yyconst flex_int16_t yy_def[416] = + { 0, + 410, 1, 411, 411, 410, 5, 410, 410, 410, 410, + 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, + 410, 410, 410, 410, 410, 410, 410, 410, 410, 412, + 410, 410, 410, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 410, 410, 410, 410, 410, 410, 410, + 410, 410, 413, 410, 410, 410, 410, 410, 410, 410, + 410, 410, 410, 410, 410, 414, 410, 410, 410, 410, + 410, 415, 410, 410, 410, 410, 410, 410, 410, 410, + 410, 412, 410, 410, 412, 412, 412, 412, 412, 412, + + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 410, 410, 410, 413, + 410, 414, 410, 410, 410, 410, 415, 410, 410, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 410, 410, + 410, 410, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + + 412, 412, 412, 412, 412, 412, 412, 412, 412, 0, + 410, 410, 410, 410, 410 + } ; + +static yyconst flex_int16_t yy_nxt[671] = + { 0, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 23, 23, 23, 23, + 24, 25, 26, 27, 28, 29, 30, 30, 30, 30, + 30, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 30, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 30, 30, 30, 54, + 55, 56, 57, 59, 59, 65, 66, 90, 91, 60, + 60, 8, 61, 62, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 63, 63, 63, + + 63, 63, 63, 8, 8, 8, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 8, 8, 8, 8, 67, 70, 72, 74, 74, 74, + 74, 74, 74, 93, 157, 75, 95, 96, 73, 71, + 76, 97, 68, 98, 94, 123, 409, 99, 141, 124, + 77, 78, 142, 79, 79, 79, 79, 79, 80, 78, + 408, 83, 83, 83, 83, 83, 83, 100, 81, 85, + 82, 107, 147, 108, 407, 103, 81, 101, 81, 104, + 102, 110, 109, 125, 105, 86, 81, 87, 88, 111, + + 106, 112, 119, 116, 113, 82, 126, 132, 128, 120, + 114, 117, 229, 230, 133, 134, 121, 137, 204, 148, + 138, 143, 118, 129, 135, 144, 130, 136, 139, 216, + 406, 217, 405, 205, 145, 140, 74, 74, 74, 74, + 74, 74, 153, 153, 153, 153, 153, 153, 396, 184, + 404, 151, 185, 186, 190, 211, 187, 154, 188, 397, + 403, 151, 191, 212, 402, 401, 78, 154, 79, 79, + 79, 79, 79, 80, 78, 400, 80, 80, 80, 80, + 80, 80, 399, 81, 156, 156, 156, 156, 156, 156, + 155, 81, 155, 81, 398, 156, 156, 156, 156, 156, + + 156, 81, 78, 395, 83, 83, 83, 83, 83, 83, + 254, 255, 256, 394, 393, 219, 392, 219, 275, 81, + 220, 220, 220, 220, 220, 220, 276, 391, 390, 81, + 153, 153, 153, 153, 153, 153, 280, 281, 282, 389, + 388, 221, 387, 221, 386, 154, 222, 222, 222, 222, + 222, 222, 288, 289, 290, 154, 156, 156, 156, 156, + 156, 156, 220, 220, 220, 220, 220, 220, 220, 220, + 220, 220, 220, 220, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 297, 298, 299, 304, + 305, 306, 308, 309, 310, 316, 317, 318, 58, 58, + + 58, 58, 92, 92, 150, 150, 152, 385, 152, 152, + 384, 383, 382, 381, 380, 379, 378, 377, 376, 375, + 374, 373, 372, 371, 370, 369, 368, 367, 366, 365, + 364, 363, 362, 361, 360, 359, 358, 357, 356, 355, + 354, 353, 352, 351, 350, 349, 348, 347, 346, 345, + 344, 343, 342, 341, 340, 339, 338, 337, 336, 335, + 334, 333, 332, 331, 330, 329, 328, 327, 326, 325, + 324, 323, 322, 321, 320, 319, 315, 314, 313, 312, + 311, 307, 303, 302, 301, 300, 296, 295, 294, 293, + 292, 291, 287, 286, 285, 284, 283, 279, 278, 277, + + 274, 273, 272, 271, 270, 269, 268, 267, 266, 265, + 264, 263, 262, 261, 260, 259, 258, 257, 253, 252, + 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, + 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, + 231, 228, 227, 226, 225, 224, 223, 218, 215, 214, + 213, 210, 209, 208, 207, 206, 203, 202, 201, 200, + 199, 198, 197, 196, 195, 194, 193, 192, 189, 183, + 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, + 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, + 162, 161, 160, 159, 158, 149, 146, 131, 127, 122, + + 115, 89, 84, 69, 64, 410, 7, 410, 410, 410, + 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, + 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, + 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, + 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, + 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, + 410, 410, 410, 410, 410, 410, 410, 410, 410, 410 + } ; + +static yyconst flex_int16_t yy_chk[671] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 3, 4, 12, 12, 28, 28, 3, + 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 13, 17, 19, 20, 20, 20, + 20, 20, 20, 33, 415, 21, 34, 34, 19, 17, + 21, 35, 13, 35, 33, 44, 408, 35, 51, 44, + 21, 22, 51, 22, 22, 22, 22, 22, 22, 23, + 407, 23, 23, 23, 23, 23, 23, 36, 22, 26, + 22, 38, 55, 38, 397, 37, 23, 36, 22, 37, + 36, 39, 38, 45, 37, 26, 23, 26, 26, 39, + + 37, 39, 42, 41, 39, 22, 45, 49, 47, 42, + 39, 41, 167, 167, 49, 49, 42, 50, 135, 55, + 50, 52, 41, 47, 49, 52, 47, 49, 50, 145, + 396, 145, 395, 135, 52, 50, 74, 74, 74, 74, + 74, 74, 78, 78, 78, 78, 78, 78, 381, 120, + 393, 74, 120, 120, 122, 141, 120, 78, 120, 381, + 392, 74, 122, 141, 391, 388, 79, 78, 79, 79, + 79, 79, 79, 79, 80, 387, 80, 80, 80, 80, + 80, 80, 385, 79, 155, 155, 155, 155, 155, 155, + 81, 80, 81, 79, 382, 81, 81, 81, 81, 81, + + 81, 80, 83, 380, 83, 83, 83, 83, 83, 83, + 192, 192, 192, 379, 378, 151, 376, 151, 211, 83, + 151, 151, 151, 151, 151, 151, 211, 375, 374, 83, + 153, 153, 153, 153, 153, 153, 215, 215, 215, 371, + 370, 154, 369, 154, 368, 153, 154, 154, 154, 154, + 154, 154, 226, 226, 226, 153, 156, 156, 156, 156, + 156, 156, 219, 219, 219, 219, 219, 219, 220, 220, + 220, 220, 220, 220, 221, 221, 221, 221, 221, 221, + 222, 222, 222, 222, 222, 222, 234, 234, 234, 241, + 241, 241, 245, 245, 245, 251, 251, 251, 411, 411, + + 411, 411, 412, 412, 413, 413, 414, 367, 414, 414, + 366, 365, 364, 359, 356, 353, 352, 351, 350, 349, + 347, 345, 344, 343, 342, 340, 339, 337, 335, 334, + 333, 332, 331, 330, 329, 327, 326, 325, 324, 323, + 322, 321, 320, 319, 315, 314, 311, 300, 296, 295, + 294, 293, 286, 285, 284, 279, 278, 277, 276, 275, + 274, 271, 270, 269, 268, 267, 266, 265, 264, 263, + 262, 261, 260, 259, 258, 257, 250, 249, 248, 247, + 246, 244, 240, 239, 238, 237, 233, 232, 231, 230, + 229, 228, 225, 223, 218, 217, 216, 214, 213, 212, + + 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, + 200, 199, 198, 197, 196, 195, 194, 193, 191, 190, + 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, + 179, 177, 176, 175, 174, 173, 172, 171, 170, 169, + 168, 166, 165, 164, 163, 162, 161, 146, 144, 143, + 142, 140, 139, 138, 137, 136, 134, 133, 132, 131, + 130, 129, 128, 127, 126, 125, 124, 123, 121, 118, + 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, + 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, + 97, 96, 95, 91, 87, 60, 53, 48, 46, 43, + + 40, 27, 24, 16, 11, 7, 410, 410, 410, 410, + 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, + 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, + 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, + 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, + 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, + 410, 410, 410, 410, 410, 410, 410, 410, 410, 410 + } ; + +/* Table of booleans, true if rule could match eol. */ +static yyconst flex_int32_t yy_rule_can_match_eol[146] = + { 0, +0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, }; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +/* +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +This file contains the Lex specification for GLSL ES. +Based on ANSI C grammar, Lex specification: +http://www.lysator.liu.se/c/ANSI-C-grammar-l.html + +IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_glslang_lexer.sh, +WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). +*/ + +#include "compiler/glslang.h" +#include "compiler/ParseHelper.h" +#include "compiler/util.h" +#include "glslang_tab.h" + +/* windows only pragma */ +#ifdef _MSC_VER +#pragma warning(disable : 4102) +#endif + +#define YY_USER_ACTION yylval->lex.line = yylineno; +#define YY_INPUT(buf, result, max_size) \ + result = string_input(buf, max_size, yyscanner); + +static int string_input(char* buf, int max_size, yyscan_t yyscanner); +static int check_type(yyscan_t yyscanner); +static int reserved_word(yyscan_t yyscanner); + +#define INITIAL 0 +#define COMMENT 1 +#define FIELDS 2 + +#define YY_EXTRA_TYPE TParseContext* + +/* Holds the entire state of the reentrant scanner. */ +struct yyguts_t + { + + /* User-defined. Not touched by flex. */ + YY_EXTRA_TYPE yyextra_r; + + /* The rest are the same as the globals declared in the non-reentrant scanner. */ + FILE *yyin_r, *yyout_r; + size_t yy_buffer_stack_top; /**< index of top of stack. */ + size_t yy_buffer_stack_max; /**< capacity of stack. */ + YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ + char yy_hold_char; + int yy_n_chars; + int yyleng_r; + char *yy_c_buf_p; + int yy_init; + int yy_start; + int yy_did_buffer_switch_on_eof; + int yy_start_stack_ptr; + int yy_start_stack_depth; + int *yy_start_stack; + yy_state_type yy_last_accepting_state; + char* yy_last_accepting_cpos; + + int yylineno_r; + int yy_flex_debug_r; + + char *yytext_r; + int yy_more_flag; + int yy_more_len; + + YYSTYPE * yylval_r; + + }; /* end struct yyguts_t */ + +static int yy_init_globals (yyscan_t yyscanner ); + + /* This must go here because YYSTYPE and YYLTYPE are included + * from bison output in section 1.*/ + # define yylval yyg->yylval_r + +int yylex_init (yyscan_t* scanner); + +int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy (yyscan_t yyscanner ); + +int yyget_debug (yyscan_t yyscanner ); + +void yyset_debug (int debug_flag ,yyscan_t yyscanner ); + +YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner ); + +void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); + +FILE *yyget_in (yyscan_t yyscanner ); + +void yyset_in (FILE * in_str ,yyscan_t yyscanner ); + +FILE *yyget_out (yyscan_t yyscanner ); + +void yyset_out (FILE * out_str ,yyscan_t yyscanner ); + +int yyget_leng (yyscan_t yyscanner ); + +char *yyget_text (yyscan_t yyscanner ); + +int yyget_lineno (yyscan_t yyscanner ); + +void yyset_lineno (int line_number ,yyscan_t yyscanner ); + +int yyget_column (yyscan_t yyscanner ); + +void yyset_column (int column_no ,yyscan_t yyscanner ); + +YYSTYPE * yyget_lval (yyscan_t yyscanner ); + +void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap (yyscan_t yyscanner ); +#else +extern int yywrap (yyscan_t yyscanner ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (yyscan_t yyscanner ); +#else +static int input (yyscan_t yyscanner ); +#endif + +#endif + + static void yy_push_state (int new_state ,yyscan_t yyscanner); + + static void yy_pop_state (yyscan_t yyscanner ); + + static int yy_top_state (yyscan_t yyscanner ); + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + unsigned n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex \ + (YYSTYPE * yylval_param ,yyscan_t yyscanner); + +#define YY_DECL int yylex \ + (YYSTYPE * yylval_param , yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + TParseContext* context = yyextra; + + /* Single-line comments */ + + yylval = yylval_param; + + if ( !yyg->yy_init ) + { + yyg->yy_init = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yyg->yy_start ) + yyg->yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + yy_load_buffer_state(yyscanner ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yyg->yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yyg->yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yyg->yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 411 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_current_state != 410 ); + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + + if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) + { + int yyl; + for ( yyl = 0; yyl < yyleng; ++yyl ) + if ( yytext[yyl] == '\n' ) + + do{ yylineno++; + yycolumn=0; + }while(0) +; + } + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yyg->yy_hold_char; + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +; + YY_BREAK +/* Multi-line comments */ +case 2: +YY_RULE_SETUP +{ yy_push_state(COMMENT, yyscanner); } + YY_BREAK +case 3: +case 4: +/* rule 4 can match eol */ +YY_RULE_SETUP +; + YY_BREAK +case 5: +YY_RULE_SETUP +{ yy_pop_state(yyscanner); } + YY_BREAK +case 6: +YY_RULE_SETUP +{ return(INVARIANT); } + YY_BREAK +case 7: +YY_RULE_SETUP +{ return(HIGH_PRECISION); } + YY_BREAK +case 8: +YY_RULE_SETUP +{ return(MEDIUM_PRECISION); } + YY_BREAK +case 9: +YY_RULE_SETUP +{ return(LOW_PRECISION); } + YY_BREAK +case 10: +YY_RULE_SETUP +{ return(PRECISION); } + YY_BREAK +case 11: +YY_RULE_SETUP +{ return(ATTRIBUTE); } + YY_BREAK +case 12: +YY_RULE_SETUP +{ return(CONST_QUAL); } + YY_BREAK +case 13: +YY_RULE_SETUP +{ return(UNIFORM); } + YY_BREAK +case 14: +YY_RULE_SETUP +{ return(VARYING); } + YY_BREAK +case 15: +YY_RULE_SETUP +{ return(BREAK); } + YY_BREAK +case 16: +YY_RULE_SETUP +{ return(CONTINUE); } + YY_BREAK +case 17: +YY_RULE_SETUP +{ return(DO); } + YY_BREAK +case 18: +YY_RULE_SETUP +{ return(FOR); } + YY_BREAK +case 19: +YY_RULE_SETUP +{ return(WHILE); } + YY_BREAK +case 20: +YY_RULE_SETUP +{ return(IF); } + YY_BREAK +case 21: +YY_RULE_SETUP +{ return(ELSE); } + YY_BREAK +case 22: +YY_RULE_SETUP +{ return(IN_QUAL); } + YY_BREAK +case 23: +YY_RULE_SETUP +{ return(OUT_QUAL); } + YY_BREAK +case 24: +YY_RULE_SETUP +{ return(INOUT_QUAL); } + YY_BREAK +case 25: +YY_RULE_SETUP +{ context->lexAfterType = true; return(FLOAT_TYPE); } + YY_BREAK +case 26: +YY_RULE_SETUP +{ context->lexAfterType = true; return(INT_TYPE); } + YY_BREAK +case 27: +YY_RULE_SETUP +{ context->lexAfterType = true; return(VOID_TYPE); } + YY_BREAK +case 28: +YY_RULE_SETUP +{ context->lexAfterType = true; return(BOOL_TYPE); } + YY_BREAK +case 29: +YY_RULE_SETUP +{ yylval->lex.b = true; return(BOOLCONSTANT); } + YY_BREAK +case 30: +YY_RULE_SETUP +{ yylval->lex.b = false; return(BOOLCONSTANT); } + YY_BREAK +case 31: +YY_RULE_SETUP +{ return(DISCARD); } + YY_BREAK +case 32: +YY_RULE_SETUP +{ return(RETURN); } + YY_BREAK +case 33: +YY_RULE_SETUP +{ context->lexAfterType = true; return(MATRIX2); } + YY_BREAK +case 34: +YY_RULE_SETUP +{ context->lexAfterType = true; return(MATRIX3); } + YY_BREAK +case 35: +YY_RULE_SETUP +{ context->lexAfterType = true; return(MATRIX4); } + YY_BREAK +case 36: +YY_RULE_SETUP +{ context->lexAfterType = true; return (VEC2); } + YY_BREAK +case 37: +YY_RULE_SETUP +{ context->lexAfterType = true; return (VEC3); } + YY_BREAK +case 38: +YY_RULE_SETUP +{ context->lexAfterType = true; return (VEC4); } + YY_BREAK +case 39: +YY_RULE_SETUP +{ context->lexAfterType = true; return (IVEC2); } + YY_BREAK +case 40: +YY_RULE_SETUP +{ context->lexAfterType = true; return (IVEC3); } + YY_BREAK +case 41: +YY_RULE_SETUP +{ context->lexAfterType = true; return (IVEC4); } + YY_BREAK +case 42: +YY_RULE_SETUP +{ context->lexAfterType = true; return (BVEC2); } + YY_BREAK +case 43: +YY_RULE_SETUP +{ context->lexAfterType = true; return (BVEC3); } + YY_BREAK +case 44: +YY_RULE_SETUP +{ context->lexAfterType = true; return (BVEC4); } + YY_BREAK +case 45: +YY_RULE_SETUP +{ context->lexAfterType = true; return SAMPLER2D; } + YY_BREAK +case 46: +YY_RULE_SETUP +{ context->lexAfterType = true; return SAMPLERCUBE; } + YY_BREAK +case 47: +YY_RULE_SETUP +{ context->lexAfterType = true; return(STRUCT); } + YY_BREAK +case 48: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 49: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 50: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 51: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 52: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 53: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 54: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 55: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 56: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 57: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 58: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 59: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 60: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 61: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 62: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 63: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 64: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 65: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 66: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 67: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 68: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 69: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 70: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 71: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 72: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 73: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 74: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 75: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 76: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 77: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 78: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 79: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 80: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 81: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 82: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 83: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 84: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 85: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 86: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 87: +YY_RULE_SETUP +{ return reserved_word(yyscanner); } + YY_BREAK +case 88: +YY_RULE_SETUP +{ + yylval->lex.string = NewPoolTString(yytext); + return check_type(yyscanner); +} + YY_BREAK +case 89: +YY_RULE_SETUP +{ yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } + YY_BREAK +case 90: +YY_RULE_SETUP +{ yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } + YY_BREAK +case 91: +YY_RULE_SETUP +{ context->error(yylineno, "Invalid Octal number.", yytext, "", ""); context->recover(); return 0;} + YY_BREAK +case 92: +YY_RULE_SETUP +{ yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } + YY_BREAK +case 93: +YY_RULE_SETUP +{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); } + YY_BREAK +case 94: +YY_RULE_SETUP +{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); } + YY_BREAK +case 95: +YY_RULE_SETUP +{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); } + YY_BREAK +case 96: +YY_RULE_SETUP +{ return(ADD_ASSIGN); } + YY_BREAK +case 97: +YY_RULE_SETUP +{ return(SUB_ASSIGN); } + YY_BREAK +case 98: +YY_RULE_SETUP +{ return(MUL_ASSIGN); } + YY_BREAK +case 99: +YY_RULE_SETUP +{ return(DIV_ASSIGN); } + YY_BREAK +case 100: +YY_RULE_SETUP +{ return(MOD_ASSIGN); } + YY_BREAK +case 101: +YY_RULE_SETUP +{ return(LEFT_ASSIGN); } + YY_BREAK +case 102: +YY_RULE_SETUP +{ return(RIGHT_ASSIGN); } + YY_BREAK +case 103: +YY_RULE_SETUP +{ return(AND_ASSIGN); } + YY_BREAK +case 104: +YY_RULE_SETUP +{ return(XOR_ASSIGN); } + YY_BREAK +case 105: +YY_RULE_SETUP +{ return(OR_ASSIGN); } + YY_BREAK +case 106: +YY_RULE_SETUP +{ return(INC_OP); } + YY_BREAK +case 107: +YY_RULE_SETUP +{ return(DEC_OP); } + YY_BREAK +case 108: +YY_RULE_SETUP +{ return(AND_OP); } + YY_BREAK +case 109: +YY_RULE_SETUP +{ return(OR_OP); } + YY_BREAK +case 110: +YY_RULE_SETUP +{ return(XOR_OP); } + YY_BREAK +case 111: +YY_RULE_SETUP +{ return(LE_OP); } + YY_BREAK +case 112: +YY_RULE_SETUP +{ return(GE_OP); } + YY_BREAK +case 113: +YY_RULE_SETUP +{ return(EQ_OP); } + YY_BREAK +case 114: +YY_RULE_SETUP +{ return(NE_OP); } + YY_BREAK +case 115: +YY_RULE_SETUP +{ return(LEFT_OP); } + YY_BREAK +case 116: +YY_RULE_SETUP +{ return(RIGHT_OP); } + YY_BREAK +case 117: +YY_RULE_SETUP +{ context->lexAfterType = false; return(SEMICOLON); } + YY_BREAK +case 118: +YY_RULE_SETUP +{ context->lexAfterType = false; return(LEFT_BRACE); } + YY_BREAK +case 119: +YY_RULE_SETUP +{ return(RIGHT_BRACE); } + YY_BREAK +case 120: +YY_RULE_SETUP +{ if (context->inTypeParen) context->lexAfterType = false; return(COMMA); } + YY_BREAK +case 121: +YY_RULE_SETUP +{ return(COLON); } + YY_BREAK +case 122: +YY_RULE_SETUP +{ context->lexAfterType = false; return(EQUAL); } + YY_BREAK +case 123: +YY_RULE_SETUP +{ context->lexAfterType = false; context->inTypeParen = true; return(LEFT_PAREN); } + YY_BREAK +case 124: +YY_RULE_SETUP +{ context->inTypeParen = false; return(RIGHT_PAREN); } + YY_BREAK +case 125: +YY_RULE_SETUP +{ return(LEFT_BRACKET); } + YY_BREAK +case 126: +YY_RULE_SETUP +{ return(RIGHT_BRACKET); } + YY_BREAK +case 127: +YY_RULE_SETUP +{ BEGIN(FIELDS); return(DOT); } + YY_BREAK +case 128: +YY_RULE_SETUP +{ return(BANG); } + YY_BREAK +case 129: +YY_RULE_SETUP +{ return(DASH); } + YY_BREAK +case 130: +YY_RULE_SETUP +{ return(TILDE); } + YY_BREAK +case 131: +YY_RULE_SETUP +{ return(PLUS); } + YY_BREAK +case 132: +YY_RULE_SETUP +{ return(STAR); } + YY_BREAK +case 133: +YY_RULE_SETUP +{ return(SLASH); } + YY_BREAK +case 134: +YY_RULE_SETUP +{ return(PERCENT); } + YY_BREAK +case 135: +YY_RULE_SETUP +{ return(LEFT_ANGLE); } + YY_BREAK +case 136: +YY_RULE_SETUP +{ return(RIGHT_ANGLE); } + YY_BREAK +case 137: +YY_RULE_SETUP +{ return(VERTICAL_BAR); } + YY_BREAK +case 138: +YY_RULE_SETUP +{ return(CARET); } + YY_BREAK +case 139: +YY_RULE_SETUP +{ return(AMPERSAND); } + YY_BREAK +case 140: +YY_RULE_SETUP +{ return(QUESTION); } + YY_BREAK +case 141: +YY_RULE_SETUP +{ + BEGIN(INITIAL); + yylval->lex.string = NewPoolTString(yytext); + return FIELD_SELECTION; +} + YY_BREAK +case 142: +YY_RULE_SETUP +{} + YY_BREAK +case 143: +/* rule 143 can match eol */ +YY_RULE_SETUP +{ } + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(COMMENT): +case YY_STATE_EOF(FIELDS): +{ context->AfterEOF = true; yyterminate(); } + YY_BREAK +case 144: +YY_RULE_SETUP +{ context->warning(yylineno, "Unknown char", yytext, ""); return 0; } + YY_BREAK +case 145: +YY_RULE_SETUP +ECHO; + YY_BREAK + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yyg->yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); + + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yyg->yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_END_OF_FILE: + { + yyg->yy_did_buffer_switch_on_eof = 0; + + if ( yywrap(yyscanner ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = + yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yyg->yy_c_buf_p = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = yyg->yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) (yyg->yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + yyg->yy_n_chars, (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + if ( yyg->yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin ,yyscanner); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + yyg->yy_n_chars += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (yyscan_t yyscanner) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_current_state = yyg->yy_start; + + for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 411 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) +{ + register int yy_is_jam; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ + register char *yy_cp = yyg->yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 411 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 410); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (yyscan_t yyscanner) +#else + static int input (yyscan_t yyscanner) +#endif + +{ + int c; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + *yyg->yy_c_buf_p = yyg->yy_hold_char; + + if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + /* This was really a NUL. */ + *yyg->yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yyg->yy_c_buf_p - yyg->yytext_ptr; + ++yyg->yy_c_buf_p; + + switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin ,yyscanner); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap(yyscanner ) ) + return EOF; + + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(yyscanner); +#else + return input(yyscanner); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = yyg->yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ + *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ + yyg->yy_hold_char = *++yyg->yy_c_buf_p; + + if ( c == '\n' ) + + do{ yylineno++; + yycolumn=0; + }while(0) +; + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * @param yyscanner The scanner object. + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); + yy_load_buffer_state(yyscanner ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * @param yyscanner The scanner object. + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (yyscanner); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state(yyscanner ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yyg->yy_did_buffer_switch_on_eof = 1; +} + +static void yy_load_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + yyg->yy_hold_char = *yyg->yy_c_buf_p; +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * @param yyscanner The scanner object. + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ,yyscanner ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b,file ,yyscanner); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * @param yyscanner The scanner object. + */ + void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree((void *) b->yy_ch_buf ,yyscanner ); + + yyfree((void *) b ,yyscanner ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) + +{ + int oerrno = errno; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_flush_buffer(b ,yyscanner); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * @param yyscanner The scanner object. + */ + void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state(yyscanner ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * @param yyscanner The scanner object. + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(yyscanner); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + yyg->yy_buffer_stack_top++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * @param yyscanner The scanner object. + */ +void yypop_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner); + YY_CURRENT_BUFFER_LVALUE = NULL; + if (yyg->yy_buffer_stack_top > 0) + --yyg->yy_buffer_stack_top; + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (yyscan_t yyscanner) +{ + int num_to_alloc; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (!yyg->yy_buffer_stack) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + yyg->yy_buffer_stack_max = num_to_alloc; + yyg->yy_buffer_stack_top = 0; + return; + } + + if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = yyg->yy_buffer_stack_max + grow_size; + yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc + (yyg->yy_buffer_stack, + num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); + yyg->yy_buffer_stack_max = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b ,yyscanner ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (yyconst char * yystr , yyscan_t yyscanner) +{ + + return yy_scan_bytes(yystr,strlen(yystr) ,yyscanner); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) yyalloc(n ,yyscanner ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf,n ,yyscanner); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + + static void yy_push_state (int new_state , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( yyg->yy_start_stack_ptr >= yyg->yy_start_stack_depth ) + { + yy_size_t new_size; + + yyg->yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yyg->yy_start_stack_depth * sizeof( int ); + + if ( ! yyg->yy_start_stack ) + yyg->yy_start_stack = (int *) yyalloc(new_size ,yyscanner ); + + else + yyg->yy_start_stack = (int *) yyrealloc((void *) yyg->yy_start_stack,new_size ,yyscanner ); + + if ( ! yyg->yy_start_stack ) + YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); + } + + yyg->yy_start_stack[yyg->yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); +} + + static void yy_pop_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( --yyg->yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yyg->yy_start_stack[yyg->yy_start_stack_ptr]); +} + + static int yy_top_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyg->yy_start_stack[yyg->yy_start_stack_ptr - 1]; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = yyg->yy_hold_char; \ + yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ + yyg->yy_hold_char = *yyg->yy_c_buf_p; \ + *yyg->yy_c_buf_p = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the user-defined data for this scanner. + * @param yyscanner The scanner object. + */ +YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyextra; +} + +/** Get the current line number. + * @param yyscanner The scanner object. + */ +int yyget_lineno (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yylineno; +} + +/** Get the current column number. + * @param yyscanner The scanner object. + */ +int yyget_column (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yycolumn; +} + +/** Get the input stream. + * @param yyscanner The scanner object. + */ +FILE *yyget_in (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyin; +} + +/** Get the output stream. + * @param yyscanner The scanner object. + */ +FILE *yyget_out (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyout; +} + +/** Get the length of the current token. + * @param yyscanner The scanner object. + */ +int yyget_leng (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyleng; +} + +/** Get the current token. + * @param yyscanner The scanner object. + */ + +char *yyget_text (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yytext; +} + +/** Set the user-defined data. This data is never touched by the scanner. + * @param user_defined The data to be associated with this scanner. + * @param yyscanner The scanner object. + */ +void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyextra = user_defined ; +} + +/** Set the current line number. + * @param line_number + * @param yyscanner The scanner object. + */ +void yyset_lineno (int line_number , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* lineno is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "yyset_lineno called with no buffer" , yyscanner); + + yylineno = line_number; +} + +/** Set the current column. + * @param line_number + * @param yyscanner The scanner object. + */ +void yyset_column (int column_no , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* column is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "yyset_column called with no buffer" , yyscanner); + + yycolumn = column_no; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * @param yyscanner The scanner object. + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * in_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyin = in_str ; +} + +void yyset_out (FILE * out_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyout = out_str ; +} + +int yyget_debug (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yy_flex_debug; +} + +void yyset_debug (int bdebug , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yy_flex_debug = bdebug ; +} + +/* Accessor methods for yylval and yylloc */ + +YYSTYPE * yyget_lval (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yylval; +} + +void yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yylval = yylval_param; +} + +/* User-visible API */ + +/* yylex_init is special because it creates the scanner itself, so it is + * the ONLY reentrant function that doesn't take the scanner as the last argument. + * That's why we explicitly handle the declaration, instead of using our macros. + */ + +int yylex_init(yyscan_t* ptr_yy_globals) + +{ + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + return yy_init_globals ( *ptr_yy_globals ); +} + +/* yylex_init_extra has the same functionality as yylex_init, but follows the + * convention of taking the scanner as the last argument. Note however, that + * this is a *pointer* to a scanner, as it will be allocated by this call (and + * is the reason, too, why this function also must handle its own declaration). + * The user defined value in the first argument will be available to yyalloc in + * the yyextra field. + */ + +int yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) + +{ + struct yyguts_t dummy_yyguts; + + yyset_extra (yy_user_defined, &dummy_yyguts); + + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in + yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + yyset_extra (yy_user_defined, *ptr_yy_globals); + + return yy_init_globals ( *ptr_yy_globals ); +} + +static int yy_init_globals (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + yyg->yy_buffer_stack = 0; + yyg->yy_buffer_stack_top = 0; + yyg->yy_buffer_stack_max = 0; + yyg->yy_c_buf_p = (char *) 0; + yyg->yy_init = 0; + yyg->yy_start = 0; + + yyg->yy_start_stack_ptr = 0; + yyg->yy_start_stack_depth = 0; + yyg->yy_start_stack = NULL; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(yyscanner); + } + + /* Destroy the stack itself. */ + yyfree(yyg->yy_buffer_stack ,yyscanner); + yyg->yy_buffer_stack = NULL; + + /* Destroy the start condition stack. */ + yyfree(yyg->yy_start_stack ,yyscanner ); + yyg->yy_start_stack = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( yyscanner); + + /* Destroy the main struct (reentrant only). */ + yyfree ( yyscanner , yyscanner ); + yyscanner = NULL; + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size , yyscan_t yyscanner) +{ + return (void *) malloc( size ); +} + +void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void yyfree (void * ptr , yyscan_t yyscanner) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +extern "C" { +// Preprocessor interface. +#include "compiler/preprocessor/preprocess.h" + +#define SETUP_CONTEXT(pp) \ + TParseContext* context = (TParseContext*) pp->pC; \ + struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; + +// Preprocessor callbacks. +void CPPDebugLogMsg(const char *msg) +{ + SETUP_CONTEXT(cpp); + context->infoSink.debug.message(EPrefixNone, msg); +} + +void CPPWarningToInfoLog(const char *msg) +{ + SETUP_CONTEXT(cpp); + context->warning(yylineno, msg, "", ""); +} + +void CPPShInfoLogMsg(const char *msg) +{ + SETUP_CONTEXT(cpp); + context->error(yylineno, msg, "", ""); + context->recover(); +} + +void CPPErrorToInfoLog(char *msg) +{ + SETUP_CONTEXT(cpp); + context->error(yylineno, msg, "", ""); + context->recover(); +} + +void SetLineNumber(int line) +{ + SETUP_CONTEXT(cpp); + int string = 0; + DecodeSourceLoc(yylineno, &string, NULL); + yylineno = EncodeSourceLoc(string, line); +} + +void SetStringNumber(int string) +{ + SETUP_CONTEXT(cpp); + int line = 0; + DecodeSourceLoc(yylineno, NULL, &line); + yylineno = EncodeSourceLoc(string, line); +} + +int GetStringNumber() +{ + SETUP_CONTEXT(cpp); + int string = 0; + DecodeSourceLoc(yylineno, &string, NULL); + return string; +} + +int GetLineNumber() +{ + SETUP_CONTEXT(cpp); + int line = 0; + DecodeSourceLoc(yylineno, NULL, &line); + return line; +} + +void IncLineNumber() +{ + SETUP_CONTEXT(cpp); + int string = 0, line = 0; + DecodeSourceLoc(yylineno, &string, &line); + yylineno = EncodeSourceLoc(string, ++line); +} + +void DecLineNumber() +{ + SETUP_CONTEXT(cpp); + int string = 0, line = 0; + DecodeSourceLoc(yylineno, &string, &line); + yylineno = EncodeSourceLoc(string, --line); +} + +void HandlePragma(const char **tokens, int numTokens) +{ + SETUP_CONTEXT(cpp); + if (!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")) + context->contextPragma.optimize = true; + else if (!strcmp(tokens[2], "off")) + context->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")) + context->contextPragma.debug = true; + else if (!strcmp(tokens[2], "off")) + context->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) +{ + SETUP_CONTEXT(cpp); + TString strSrc; + strSrc = TString(string); + + context->HashErrMsg = context->HashErrMsg + " " + strSrc; +} + +const char* GetStrfromTStr(void) +{ + SETUP_CONTEXT(cpp); + cpp->ErrMsg = context->HashErrMsg.c_str(); + return cpp->ErrMsg; +} + +void ResetTString(void) +{ + SETUP_CONTEXT(cpp); + context->HashErrMsg = ""; +} + +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) +{ + SETUP_CONTEXT(cpp); + 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 = context->extensionBehavior.begin(); iter != context->extensionBehavior.end(); ++iter) + iter->second = behaviorVal; + } + } else { + iter = context->extensionBehavior.find(TString(extName)); + if (iter == context->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"; + context->infoSink.info.message(EPrefixWarning, msg.c_str(), yylineno); + break; + } + return; + } else + iter->second = behaviorVal; + } +} +} // extern "C" + +int string_input(char* buf, int max_size, yyscan_t yyscanner) { + 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; +} + +int check_type(yyscan_t yyscanner) { + struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; + + int token = IDENTIFIER; + TSymbol* symbol = yyextra->symbolTable.find(yytext); + if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) { + TVariable* variable = static_cast<TVariable*>(symbol); + if (variable->isUserType()) { + yyextra->lexAfterType = true; + token = TYPE_NAME; + } + } + yylval->lex.symbol = symbol; + return token; +} + +int reserved_word(yyscan_t yyscanner) { + struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; + + yyextra->error(yylineno, "Illegal use of reserved word", yytext, ""); + yyextra->recover(); + return 0; +} + +void yyerror(TParseContext* context, const char* reason) { + struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; + + if (context->AfterEOF) { + context->error(yylineno, reason, "unexpected EOF", ""); + } else { + context->error(yylineno, reason, yytext, ""); + } + context->recover(); +} + +int glslang_initialize(TParseContext* context) { + yyscan_t scanner = NULL; + if (yylex_init_extra(context,&scanner)) + return 1; + + context->scanner = scanner; + return 0; +} + +int glslang_finalize(TParseContext* context) { + yyscan_t scanner = context->scanner; + if (scanner == NULL) return 0; + + context->scanner = NULL; + return yylex_destroy(scanner); +} + +void glslang_scan(int count, const char* const string[], const int length[], + TParseContext* context) { + yyrestart(NULL,context->scanner); + yyset_lineno(EncodeSourceLoc(0, 1),context->scanner); + context->AfterEOF = false; + + // Init preprocessor. + cpp->pC = context; + cpp->PaWhichStr = 0; + cpp->PaArgv = string; + cpp->PaArgc = count; + cpp->PaStrLen = length; + cpp->pastFirstStatement = 0; + ScanFromString(string[0]); +} + diff --git a/Source/ThirdParty/ANGLE/src/compiler/glslang_tab.cpp b/Source/ThirdParty/ANGLE/src/compiler/glslang_tab.cpp new file mode 100644 index 000000000..47ca2ee61 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/glslang_tab.cpp @@ -0,0 +1,4716 @@ +/* A Bison parser, made by GNU Bison 2.3. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.3" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 1 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + INVARIANT = 258, + HIGH_PRECISION = 259, + MEDIUM_PRECISION = 260, + LOW_PRECISION = 261, + PRECISION = 262, + ATTRIBUTE = 263, + CONST_QUAL = 264, + BOOL_TYPE = 265, + FLOAT_TYPE = 266, + INT_TYPE = 267, + BREAK = 268, + CONTINUE = 269, + DO = 270, + ELSE = 271, + FOR = 272, + IF = 273, + DISCARD = 274, + RETURN = 275, + BVEC2 = 276, + BVEC3 = 277, + BVEC4 = 278, + IVEC2 = 279, + IVEC3 = 280, + IVEC4 = 281, + VEC2 = 282, + VEC3 = 283, + VEC4 = 284, + MATRIX2 = 285, + MATRIX3 = 286, + MATRIX4 = 287, + IN_QUAL = 288, + OUT_QUAL = 289, + INOUT_QUAL = 290, + UNIFORM = 291, + VARYING = 292, + STRUCT = 293, + VOID_TYPE = 294, + WHILE = 295, + SAMPLER2D = 296, + SAMPLERCUBE = 297, + IDENTIFIER = 298, + TYPE_NAME = 299, + FLOATCONSTANT = 300, + INTCONSTANT = 301, + BOOLCONSTANT = 302, + FIELD_SELECTION = 303, + LEFT_OP = 304, + RIGHT_OP = 305, + INC_OP = 306, + DEC_OP = 307, + LE_OP = 308, + GE_OP = 309, + EQ_OP = 310, + NE_OP = 311, + AND_OP = 312, + OR_OP = 313, + XOR_OP = 314, + MUL_ASSIGN = 315, + DIV_ASSIGN = 316, + ADD_ASSIGN = 317, + MOD_ASSIGN = 318, + LEFT_ASSIGN = 319, + RIGHT_ASSIGN = 320, + AND_ASSIGN = 321, + XOR_ASSIGN = 322, + OR_ASSIGN = 323, + SUB_ASSIGN = 324, + LEFT_PAREN = 325, + RIGHT_PAREN = 326, + LEFT_BRACKET = 327, + RIGHT_BRACKET = 328, + LEFT_BRACE = 329, + RIGHT_BRACE = 330, + DOT = 331, + COMMA = 332, + COLON = 333, + EQUAL = 334, + SEMICOLON = 335, + BANG = 336, + DASH = 337, + TILDE = 338, + PLUS = 339, + STAR = 340, + SLASH = 341, + PERCENT = 342, + LEFT_ANGLE = 343, + RIGHT_ANGLE = 344, + VERTICAL_BAR = 345, + CARET = 346, + AMPERSAND = 347, + QUESTION = 348 + }; +#endif +/* Tokens. */ +#define INVARIANT 258 +#define HIGH_PRECISION 259 +#define MEDIUM_PRECISION 260 +#define LOW_PRECISION 261 +#define PRECISION 262 +#define ATTRIBUTE 263 +#define CONST_QUAL 264 +#define BOOL_TYPE 265 +#define FLOAT_TYPE 266 +#define INT_TYPE 267 +#define BREAK 268 +#define CONTINUE 269 +#define DO 270 +#define ELSE 271 +#define FOR 272 +#define IF 273 +#define DISCARD 274 +#define RETURN 275 +#define BVEC2 276 +#define BVEC3 277 +#define BVEC4 278 +#define IVEC2 279 +#define IVEC3 280 +#define IVEC4 281 +#define VEC2 282 +#define VEC3 283 +#define VEC4 284 +#define MATRIX2 285 +#define MATRIX3 286 +#define MATRIX4 287 +#define IN_QUAL 288 +#define OUT_QUAL 289 +#define INOUT_QUAL 290 +#define UNIFORM 291 +#define VARYING 292 +#define STRUCT 293 +#define VOID_TYPE 294 +#define WHILE 295 +#define SAMPLER2D 296 +#define SAMPLERCUBE 297 +#define IDENTIFIER 298 +#define TYPE_NAME 299 +#define FLOATCONSTANT 300 +#define INTCONSTANT 301 +#define BOOLCONSTANT 302 +#define FIELD_SELECTION 303 +#define LEFT_OP 304 +#define RIGHT_OP 305 +#define INC_OP 306 +#define DEC_OP 307 +#define LE_OP 308 +#define GE_OP 309 +#define EQ_OP 310 +#define NE_OP 311 +#define AND_OP 312 +#define OR_OP 313 +#define XOR_OP 314 +#define MUL_ASSIGN 315 +#define DIV_ASSIGN 316 +#define ADD_ASSIGN 317 +#define MOD_ASSIGN 318 +#define LEFT_ASSIGN 319 +#define RIGHT_ASSIGN 320 +#define AND_ASSIGN 321 +#define XOR_ASSIGN 322 +#define OR_ASSIGN 323 +#define SUB_ASSIGN 324 +#define LEFT_PAREN 325 +#define RIGHT_PAREN 326 +#define LEFT_BRACKET 327 +#define RIGHT_BRACKET 328 +#define LEFT_BRACE 329 +#define RIGHT_BRACE 330 +#define DOT 331 +#define COMMA 332 +#define COLON 333 +#define EQUAL 334 +#define SEMICOLON 335 +#define BANG 336 +#define DASH 337 +#define TILDE 338 +#define PLUS 339 +#define STAR 340 +#define SLASH 341 +#define PERCENT 342 +#define LEFT_ANGLE 343 +#define RIGHT_ANGLE 344 +#define VERTICAL_BAR 345 +#define CARET 346 +#define AMPERSAND 347 +#define QUESTION 348 + + + + +/* Copy the first part of user declarations. */ + + +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// This file is auto-generated by generate_glslang_parser.sh. DO NOT EDIT! + +#include "compiler/SymbolTable.h" +#include "compiler/ParseHelper.h" +#include "GLSLANG/ShaderLang.h" + +#define YYLEX_PARAM context->scanner + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE + +{ + struct { + TSourceLoc line; + union { + TString *string; + float f; + int i; + bool b; + }; + TSymbol* symbol; + } lex; + struct { + TSourceLoc line; + TOperator op; + union { + TIntermNode* intermNode; + TIntermNodePair nodePair; + TIntermTyped* intermTypedNode; + TIntermAggregate* intermAggregate; + }; + union { + TPublicType type; + TPrecision precision; + TQualifier qualifier; + TFunction* function; + TParameter param; + TTypeLine typeLine; + TTypeList* typeList; + }; + } interm; +} +/* Line 193 of yacc.c. */ + + YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ + + +extern int yylex(YYSTYPE* yylval_param, void* yyscanner); +extern void yyerror(TParseContext* context, const char* reason); + +#define FRAG_VERT_ONLY(S, L) { \ + if (context->shaderType != SH_FRAGMENT_SHADER && \ + context->shaderType != SH_VERTEX_SHADER) { \ + context->error(L, " supported in vertex/fragment shaders only ", S, "", ""); \ + context->recover(); \ + } \ +} + +#define VERTEX_ONLY(S, L) { \ + if (context->shaderType != SH_VERTEX_SHADER) { \ + context->error(L, " supported in vertex shaders only ", S, "", ""); \ + context->recover(); \ + } \ +} + +#define FRAG_ONLY(S, L) { \ + if (context->shaderType != SH_FRAGMENT_SHADER) { \ + context->error(L, " supported in fragment shaders only ", S, "", ""); \ + context->recover(); \ + } \ +} + + +/* Line 216 of yacc.c. */ + + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include <libintl.h> /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int i) +#else +static int +YYID (i) + int i; +#endif +{ + return i; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include <alloca.h> /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include <malloc.h> /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 69 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 1362 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 94 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 78 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 193 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 296 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 348 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint16 yyprhs[] = +{ + 0, 0, 3, 5, 7, 9, 11, 13, 17, 19, + 24, 26, 30, 33, 36, 38, 40, 42, 46, 49, + 52, 55, 57, 60, 64, 67, 69, 71, 73, 75, + 78, 81, 84, 86, 88, 90, 92, 96, 100, 102, + 106, 110, 112, 114, 118, 122, 126, 130, 132, 136, + 140, 142, 144, 146, 148, 152, 154, 158, 160, 164, + 166, 172, 174, 178, 180, 182, 184, 186, 188, 190, + 194, 196, 199, 202, 207, 210, 212, 214, 217, 221, + 225, 228, 234, 238, 241, 245, 248, 249, 251, 253, + 255, 257, 259, 263, 269, 276, 282, 284, 287, 292, + 298, 303, 306, 308, 311, 313, 315, 317, 320, 322, + 324, 327, 329, 331, 333, 335, 340, 342, 344, 346, + 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, + 368, 370, 372, 374, 376, 378, 380, 386, 391, 393, + 396, 400, 402, 406, 408, 413, 415, 417, 419, 421, + 423, 425, 427, 429, 431, 434, 435, 436, 442, 444, + 446, 449, 453, 455, 458, 460, 463, 469, 473, 475, + 477, 482, 483, 490, 491, 500, 501, 509, 511, 513, + 515, 516, 519, 523, 526, 529, 532, 536, 539, 541, + 544, 546, 548, 549 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int16 yyrhs[] = +{ + 168, 0, -1, 43, -1, 95, -1, 46, -1, 45, + -1, 47, -1, 70, 122, 71, -1, 96, -1, 97, + 72, 98, 73, -1, 99, -1, 97, 76, 48, -1, + 97, 51, -1, 97, 52, -1, 122, -1, 100, -1, + 101, -1, 97, 76, 101, -1, 103, 71, -1, 102, + 71, -1, 104, 39, -1, 104, -1, 104, 120, -1, + 103, 77, 120, -1, 105, 70, -1, 140, -1, 43, + -1, 48, -1, 97, -1, 51, 106, -1, 52, 106, + -1, 107, 106, -1, 84, -1, 82, -1, 81, -1, + 106, -1, 108, 85, 106, -1, 108, 86, 106, -1, + 108, -1, 109, 84, 108, -1, 109, 82, 108, -1, + 109, -1, 110, -1, 111, 88, 110, -1, 111, 89, + 110, -1, 111, 53, 110, -1, 111, 54, 110, -1, + 111, -1, 112, 55, 111, -1, 112, 56, 111, -1, + 112, -1, 113, -1, 114, -1, 115, -1, 116, 57, + 115, -1, 116, -1, 117, 59, 116, -1, 117, -1, + 118, 58, 117, -1, 118, -1, 118, 93, 122, 78, + 120, -1, 119, -1, 106, 121, 120, -1, 79, -1, + 60, -1, 61, -1, 62, -1, 69, -1, 120, -1, + 122, 77, 120, -1, 119, -1, 125, 80, -1, 133, + 80, -1, 7, 138, 139, 80, -1, 126, 71, -1, + 128, -1, 127, -1, 128, 130, -1, 127, 77, 130, + -1, 135, 43, 70, -1, 137, 43, -1, 137, 43, + 72, 123, 73, -1, 136, 131, 129, -1, 131, 129, + -1, 136, 131, 132, -1, 131, 132, -1, -1, 33, + -1, 34, -1, 35, -1, 137, -1, 134, -1, 133, + 77, 43, -1, 133, 77, 43, 72, 73, -1, 133, + 77, 43, 72, 123, 73, -1, 133, 77, 43, 79, + 146, -1, 135, -1, 135, 43, -1, 135, 43, 72, + 73, -1, 135, 43, 72, 123, 73, -1, 135, 43, + 79, 146, -1, 3, 43, -1, 137, -1, 136, 137, + -1, 9, -1, 8, -1, 37, -1, 3, 37, -1, + 36, -1, 139, -1, 138, 139, -1, 4, -1, 5, + -1, 6, -1, 140, -1, 140, 72, 123, 73, -1, + 39, -1, 11, -1, 12, -1, 10, -1, 27, -1, + 28, -1, 29, -1, 21, -1, 22, -1, 23, -1, + 24, -1, 25, -1, 26, -1, 30, -1, 31, -1, + 32, -1, 41, -1, 42, -1, 141, -1, 44, -1, + 38, 43, 74, 142, 75, -1, 38, 74, 142, 75, + -1, 143, -1, 142, 143, -1, 137, 144, 80, -1, + 145, -1, 144, 77, 145, -1, 43, -1, 43, 72, + 123, 73, -1, 120, -1, 124, -1, 150, -1, 149, + -1, 147, -1, 156, -1, 157, -1, 160, -1, 167, + -1, 74, 75, -1, -1, -1, 74, 151, 155, 152, + 75, -1, 154, -1, 149, -1, 74, 75, -1, 74, + 155, 75, -1, 148, -1, 155, 148, -1, 80, -1, + 122, 80, -1, 18, 70, 122, 71, 158, -1, 148, + 16, 148, -1, 148, -1, 122, -1, 135, 43, 79, + 146, -1, -1, 40, 70, 161, 159, 71, 153, -1, + -1, 15, 162, 148, 40, 70, 122, 71, 80, -1, + -1, 17, 70, 163, 164, 166, 71, 153, -1, 156, + -1, 147, -1, 159, -1, -1, 165, 80, -1, 165, + 80, 122, -1, 14, 80, -1, 13, 80, -1, 20, + 80, -1, 20, 122, 80, -1, 19, 80, -1, 169, + -1, 168, 169, -1, 170, -1, 124, -1, -1, 125, + 171, 154, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 153, 153, 188, 191, 204, 209, 214, 220, 223, + 296, 299, 408, 418, 431, 439, 538, 541, 549, 553, + 560, 564, 571, 577, 586, 594, 649, 656, 666, 669, + 679, 689, 710, 711, 712, 717, 718, 727, 739, 740, + 748, 759, 763, 764, 774, 784, 794, 807, 808, 818, + 831, 835, 839, 843, 844, 857, 858, 871, 872, 885, + 886, 903, 904, 917, 918, 919, 920, 921, 925, 928, + 939, 947, 972, 977, 984, 1020, 1023, 1030, 1038, 1059, + 1078, 1089, 1118, 1123, 1133, 1138, 1148, 1151, 1154, 1157, + 1163, 1170, 1173, 1189, 1207, 1231, 1254, 1258, 1276, 1284, + 1316, 1336, 1412, 1421, 1444, 1447, 1453, 1461, 1469, 1477, + 1487, 1494, 1497, 1500, 1506, 1509, 1524, 1528, 1532, 1536, + 1545, 1550, 1555, 1560, 1565, 1570, 1575, 1580, 1585, 1590, + 1596, 1602, 1608, 1613, 1618, 1623, 1636, 1649, 1657, 1660, + 1675, 1707, 1711, 1717, 1725, 1741, 1745, 1749, 1750, 1756, + 1757, 1758, 1759, 1760, 1764, 1765, 1765, 1765, 1775, 1776, + 1781, 1784, 1794, 1797, 1803, 1804, 1808, 1816, 1820, 1830, + 1835, 1852, 1852, 1857, 1857, 1864, 1864, 1872, 1875, 1881, + 1884, 1890, 1894, 1901, 1908, 1915, 1922, 1933, 1942, 1946, + 1953, 1956, 1962, 1962 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "INVARIANT", "HIGH_PRECISION", + "MEDIUM_PRECISION", "LOW_PRECISION", "PRECISION", "ATTRIBUTE", + "CONST_QUAL", "BOOL_TYPE", "FLOAT_TYPE", "INT_TYPE", "BREAK", "CONTINUE", + "DO", "ELSE", "FOR", "IF", "DISCARD", "RETURN", "BVEC2", "BVEC3", + "BVEC4", "IVEC2", "IVEC3", "IVEC4", "VEC2", "VEC3", "VEC4", "MATRIX2", + "MATRIX3", "MATRIX4", "IN_QUAL", "OUT_QUAL", "INOUT_QUAL", "UNIFORM", + "VARYING", "STRUCT", "VOID_TYPE", "WHILE", "SAMPLER2D", "SAMPLERCUBE", + "IDENTIFIER", "TYPE_NAME", "FLOATCONSTANT", "INTCONSTANT", + "BOOLCONSTANT", "FIELD_SELECTION", "LEFT_OP", "RIGHT_OP", "INC_OP", + "DEC_OP", "LE_OP", "GE_OP", "EQ_OP", "NE_OP", "AND_OP", "OR_OP", + "XOR_OP", "MUL_ASSIGN", "DIV_ASSIGN", "ADD_ASSIGN", "MOD_ASSIGN", + "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN", "XOR_ASSIGN", "OR_ASSIGN", + "SUB_ASSIGN", "LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACKET", + "RIGHT_BRACKET", "LEFT_BRACE", "RIGHT_BRACE", "DOT", "COMMA", "COLON", + "EQUAL", "SEMICOLON", "BANG", "DASH", "TILDE", "PLUS", "STAR", "SLASH", + "PERCENT", "LEFT_ANGLE", "RIGHT_ANGLE", "VERTICAL_BAR", "CARET", + "AMPERSAND", "QUESTION", "$accept", "variable_identifier", + "primary_expression", "postfix_expression", "integer_expression", + "function_call", "function_call_or_method", "function_call_generic", + "function_call_header_no_parameters", + "function_call_header_with_parameters", "function_call_header", + "function_identifier", "unary_expression", "unary_operator", + "multiplicative_expression", "additive_expression", "shift_expression", + "relational_expression", "equality_expression", "and_expression", + "exclusive_or_expression", "inclusive_or_expression", + "logical_and_expression", "logical_xor_expression", + "logical_or_expression", "conditional_expression", + "assignment_expression", "assignment_operator", "expression", + "constant_expression", "declaration", "function_prototype", + "function_declarator", "function_header_with_parameters", + "function_header", "parameter_declarator", "parameter_declaration", + "parameter_qualifier", "parameter_type_specifier", + "init_declarator_list", "single_declaration", "fully_specified_type", + "type_qualifier", "type_specifier", "precision_qualifier", + "type_specifier_no_prec", "type_specifier_nonarray", "struct_specifier", + "struct_declaration_list", "struct_declaration", + "struct_declarator_list", "struct_declarator", "initializer", + "declaration_statement", "statement", "simple_statement", + "compound_statement", "@1", "@2", "statement_no_new_scope", + "compound_statement_no_new_scope", "statement_list", + "expression_statement", "selection_statement", + "selection_rest_statement", "condition", "iteration_statement", "@3", + "@4", "@5", "for_init_statement", "conditionopt", "for_rest_statement", + "jump_statement", "translation_unit", "external_declaration", + "function_definition", "@6", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, + 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, 347, 348 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 94, 95, 96, 96, 96, 96, 96, 97, 97, + 97, 97, 97, 97, 98, 99, 100, 100, 101, 101, + 102, 102, 103, 103, 104, 105, 105, 105, 106, 106, + 106, 106, 107, 107, 107, 108, 108, 108, 109, 109, + 109, 110, 111, 111, 111, 111, 111, 112, 112, 112, + 113, 114, 115, 116, 116, 117, 117, 118, 118, 119, + 119, 120, 120, 121, 121, 121, 121, 121, 122, 122, + 123, 124, 124, 124, 125, 126, 126, 127, 127, 128, + 129, 129, 130, 130, 130, 130, 131, 131, 131, 131, + 132, 133, 133, 133, 133, 133, 134, 134, 134, 134, + 134, 134, 135, 135, 136, 136, 136, 136, 136, 137, + 137, 138, 138, 138, 139, 139, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 141, 141, 142, 142, + 143, 144, 144, 145, 145, 146, 147, 148, 148, 149, + 149, 149, 149, 149, 150, 151, 152, 150, 153, 153, + 154, 154, 155, 155, 156, 156, 157, 158, 158, 159, + 159, 161, 160, 162, 160, 163, 160, 164, 164, 165, + 165, 166, 166, 167, 167, 167, 167, 167, 168, 168, + 169, 169, 171, 170 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 1, 1, 1, 1, 1, 3, 1, 4, + 1, 3, 2, 2, 1, 1, 1, 3, 2, 2, + 2, 1, 2, 3, 2, 1, 1, 1, 1, 2, + 2, 2, 1, 1, 1, 1, 3, 3, 1, 3, + 3, 1, 1, 3, 3, 3, 3, 1, 3, 3, + 1, 1, 1, 1, 3, 1, 3, 1, 3, 1, + 5, 1, 3, 1, 1, 1, 1, 1, 1, 3, + 1, 2, 2, 4, 2, 1, 1, 2, 3, 3, + 2, 5, 3, 2, 3, 2, 0, 1, 1, 1, + 1, 1, 3, 5, 6, 5, 1, 2, 4, 5, + 4, 2, 1, 2, 1, 1, 1, 2, 1, 1, + 2, 1, 1, 1, 1, 4, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 5, 4, 1, 2, + 3, 1, 3, 1, 4, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 0, 0, 5, 1, 1, + 2, 3, 1, 2, 1, 2, 5, 3, 1, 1, + 4, 0, 6, 0, 8, 0, 7, 1, 1, 1, + 0, 2, 3, 2, 2, 2, 3, 2, 1, 2, + 1, 1, 0, 3 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 0, 0, 111, 112, 113, 0, 105, 104, 119, 117, + 118, 123, 124, 125, 126, 127, 128, 120, 121, 122, + 129, 130, 131, 108, 106, 0, 116, 132, 133, 135, + 191, 192, 0, 76, 86, 0, 91, 96, 0, 102, + 0, 109, 114, 134, 0, 188, 190, 107, 101, 0, + 0, 0, 71, 0, 74, 86, 0, 87, 88, 89, + 77, 0, 86, 0, 72, 97, 103, 110, 0, 1, + 189, 0, 0, 0, 0, 138, 0, 193, 78, 83, + 85, 90, 0, 92, 79, 0, 0, 2, 5, 4, + 6, 27, 0, 0, 0, 34, 33, 32, 3, 8, + 28, 10, 15, 16, 0, 0, 21, 0, 35, 0, + 38, 41, 42, 47, 50, 51, 52, 53, 55, 57, + 59, 70, 0, 25, 73, 0, 143, 0, 141, 137, + 139, 0, 0, 173, 0, 0, 0, 0, 0, 155, + 160, 164, 35, 61, 68, 0, 146, 0, 114, 149, + 162, 148, 147, 0, 150, 151, 152, 153, 80, 82, + 84, 0, 0, 98, 0, 145, 100, 29, 30, 0, + 12, 13, 0, 0, 19, 18, 0, 20, 22, 24, + 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 115, 136, 0, 0, 140, + 184, 183, 0, 175, 0, 187, 185, 0, 171, 154, + 0, 64, 65, 66, 67, 63, 0, 0, 165, 161, + 163, 0, 93, 0, 95, 99, 7, 0, 14, 26, + 11, 17, 23, 36, 37, 40, 39, 45, 46, 43, + 44, 48, 49, 54, 56, 58, 0, 0, 142, 0, + 0, 0, 186, 0, 156, 62, 69, 0, 94, 9, + 0, 144, 0, 178, 177, 180, 0, 169, 0, 0, + 0, 81, 60, 0, 179, 0, 0, 168, 166, 0, + 0, 157, 0, 181, 0, 0, 0, 159, 172, 158, + 0, 182, 176, 167, 170, 174 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 98, 99, 100, 227, 101, 102, 103, 104, 105, + 106, 107, 142, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 143, 144, 216, 145, 122, + 146, 147, 32, 33, 34, 79, 60, 61, 80, 35, + 36, 37, 38, 39, 40, 41, 123, 43, 74, 75, + 127, 128, 166, 149, 150, 151, 152, 210, 270, 288, + 289, 153, 154, 155, 278, 269, 156, 253, 202, 250, + 265, 275, 276, 157, 44, 45, 46, 53 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -250 +static const yytype_int16 yypact[] = +{ + 1218, -13, -250, -250, -250, 137, -250, -250, -250, -250, + -250, -250, -250, -250, -250, -250, -250, -250, -250, -250, + -250, -250, -250, -250, -250, -28, -250, -250, -250, -250, + -250, -55, -38, -4, 33, -20, -250, 44, 1259, -250, + 1318, -250, 18, -250, 1176, -250, -250, -250, -250, 1318, + -22, 1259, -250, 29, -250, 85, 73, -250, -250, -250, + -250, 1259, 113, 70, -250, 13, -250, -250, 949, -250, + -250, 49, 1259, 90, 1080, -250, 283, -250, -250, -250, + -250, 101, 1259, -56, -250, 757, 949, 80, -250, -250, + -250, -250, 949, 949, 949, -250, -250, -250, -250, -250, + -33, -250, -250, -250, 81, -15, 1013, 92, -250, 949, + 52, -75, -250, -25, 40, -250, -250, -250, 106, 105, + -46, -250, 93, -250, -250, 1121, 95, 9, -250, -250, + -250, 88, 89, -250, 100, 102, 91, 821, 104, 103, + -250, -250, 66, -250, -250, 20, -250, -55, 79, -250, + -250, -250, -250, 365, -250, -250, -250, -250, 107, -250, + -250, 885, 949, -250, 109, -250, -250, -250, -250, -6, + -250, -250, 949, 1283, -250, -250, 949, 110, -250, -250, + -250, 949, 949, 949, 949, 949, 949, 949, 949, 949, + 949, 949, 949, 949, 949, -250, -250, 949, 90, -250, + -250, -250, 447, -250, 949, -250, -250, 34, -250, -250, + 447, -250, -250, -250, -250, -250, 949, 949, -250, -250, + -250, 949, -250, 111, -250, -250, -250, 112, 99, -250, + 116, -250, -250, -250, -250, 52, 52, -250, -250, -250, + -250, -25, -25, -250, 106, 105, 77, 114, -250, 125, + 611, 4, -250, 693, 447, -250, -250, 115, -250, -250, + 949, -250, 119, -250, -250, 693, 447, 99, 134, 122, + 108, -250, -250, 949, -250, 117, 123, 174, -250, 120, + 529, -250, 7, 949, 529, 447, 949, -250, -250, -250, + 118, 99, -250, -250, -250, -250 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -250, -250, -250, -250, -250, -250, -250, 22, -250, -250, + -250, -250, 31, -250, -27, -250, -79, -30, -250, -250, + -250, 5, 8, 12, -250, -63, -85, -250, -92, -82, + 10, 11, -250, -250, -250, 121, 149, 144, 126, -250, + -250, -233, -21, -24, 202, -23, 0, -250, 139, -66, + -250, 27, -156, -41, -149, -249, -250, -250, -250, -58, + 176, 17, -19, -250, -250, -35, -250, -250, -250, -250, + -250, -250, -250, -250, -250, 188, -250, -250 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -117 +static const yytype_int16 yytable[] = +{ + 42, 165, 169, 164, 220, 121, 224, 183, 130, 184, + 30, 31, 193, 62, 66, 50, 161, 67, 170, 171, + 268, 178, 121, 162, 47, 52, 71, 73, 185, 186, + 48, 287, 268, 54, 62, 287, 56, 81, 42, 172, + 42, 6, 7, 173, 42, 207, 51, 194, 73, 42, + 73, 42, 72, 249, 30, 31, 175, 63, 81, 130, + 64, 42, 176, 187, 188, 226, 57, 58, 59, 23, + 24, 217, 42, 55, 42, 266, 148, 165, 290, 223, + 228, 217, 42, 84, 217, 85, 198, 65, 56, 199, + 68, 232, 86, 6, 7, 189, 190, 217, 121, 108, + 218, 73, 246, 76, -75, 220, 237, 238, 239, 240, + 47, 217, 251, 83, 252, 247, 108, 277, 57, 58, + 59, 23, 24, 167, 168, 42, 211, 212, 213, 124, + 294, 255, 256, 126, 121, 214, 293, 181, 182, 257, + 180, 2, 3, 4, 158, 215, 57, 58, 59, -25, + -26, 68, 174, 148, 217, 260, 235, 236, 121, 241, + 242, 267, 179, 191, 192, 262, 195, 197, 200, 201, + 203, 205, 204, 267, 208, 272, 217, 279, 209, 221, + -116, 282, 225, 281, 258, 259, -27, 261, 271, 273, + 285, 291, 108, 280, 284, 231, 243, 283, 295, 286, + 244, 165, 148, 159, 78, 245, 82, 49, 160, 263, + 148, 125, 233, 234, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 248, 292, 254, 108, 77, + 274, 264, 70, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 148, 0, 108, 148, 148, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 148, 148, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 148, 0, 0, 0, 148, 148, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 131, 132, 133, 0, + 134, 135, 136, 137, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 0, 0, 0, 23, + 24, 25, 26, 138, 27, 28, 87, 29, 88, 89, + 90, 91, 0, 0, 92, 93, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 94, 0, 0, 0, 139, 140, 0, + 0, 0, 0, 141, 95, 96, 0, 97, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 131, 132, + 133, 0, 134, 135, 136, 137, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, + 0, 23, 24, 25, 26, 138, 27, 28, 87, 29, + 88, 89, 90, 91, 0, 0, 92, 93, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 0, 0, 0, 139, + 219, 0, 0, 0, 0, 141, 95, 96, 0, 97, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 131, 132, 133, 0, 134, 135, 136, 137, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 0, 0, 0, 23, 24, 25, 26, 138, 27, 28, + 87, 29, 88, 89, 90, 91, 0, 0, 92, 93, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 94, 0, 0, + 0, 139, 0, 0, 0, 0, 0, 141, 95, 96, + 0, 97, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 131, 132, 133, 0, 134, 135, 136, 137, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 0, 0, 0, 23, 24, 25, 26, 138, + 27, 28, 87, 29, 88, 89, 90, 91, 0, 0, + 92, 93, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 0, 0, 0, 76, 0, 0, 0, 0, 0, 141, + 95, 96, 0, 97, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 0, 0, 0, 23, 24, 25, + 26, 0, 27, 28, 87, 29, 88, 89, 90, 91, + 0, 0, 92, 93, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 141, 95, 96, 0, 97, 56, 2, 3, 4, + 0, 6, 7, 8, 9, 10, 0, 0, 0, 0, + 0, 0, 0, 0, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 0, 0, 0, 23, + 24, 25, 26, 0, 27, 28, 87, 29, 88, 89, + 90, 91, 0, 0, 92, 93, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 94, 0, 0, 0, 8, 9, 10, + 0, 0, 0, 0, 95, 96, 0, 97, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 0, 0, 0, 0, 0, 25, 26, 0, 27, 28, + 87, 29, 88, 89, 90, 91, 0, 0, 92, 93, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 94, 0, 0, + 163, 8, 9, 10, 0, 0, 0, 0, 95, 96, + 0, 97, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 0, 0, 0, 0, 0, 25, + 26, 0, 27, 28, 87, 29, 88, 89, 90, 91, + 0, 0, 92, 93, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 94, 0, 0, 0, 8, 9, 10, 0, 0, + 0, 206, 95, 96, 0, 97, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, + 0, 0, 0, 25, 26, 0, 27, 28, 87, 29, + 88, 89, 90, 91, 0, 0, 92, 93, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 0, 0, 222, 8, + 9, 10, 0, 0, 0, 0, 95, 96, 0, 97, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 0, 0, 0, 0, 0, 25, 26, 0, + 27, 28, 87, 29, 88, 89, 90, 91, 0, 0, + 92, 93, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 0, 0, 0, 8, 9, 10, 0, 0, 0, 0, + 95, 96, 0, 97, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, + 0, 25, 177, 0, 27, 28, 87, 29, 88, 89, + 90, 91, 0, 0, 92, 93, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 94, 2, 3, 4, 0, 0, 0, + 8, 9, 10, 0, 95, 96, 0, 97, 0, 0, + 0, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 0, 0, 0, 0, 0, 25, 26, + 0, 27, 28, 0, 29, 2, 3, 4, 0, 0, + 0, 8, 9, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 0, 129, 0, 0, 0, 25, + 26, 0, 27, 28, 0, 29, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 69, 0, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, + 0, 0, 0, 0, 0, 0, 196, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, + 0, 0, 23, 24, 25, 26, 0, 27, 28, 0, + 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 0, 0, 0, 23, 24, 25, 26, 0, 27, + 28, 0, 29, 2, 3, 4, 0, 0, 0, 8, + 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 0, 8, 9, 10, 0, 25, 26, 0, + 27, 28, 0, 29, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, + 0, 25, 26, 0, 27, 28, 229, 29, 8, 9, + 10, 230, 0, 0, 0, 0, 0, 0, 0, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 0, 0, 0, 0, 0, 25, 26, 0, 27, + 28, 0, 29 +}; + +static const yytype_int16 yycheck[] = +{ + 0, 86, 94, 85, 153, 68, 162, 82, 74, 84, + 0, 0, 58, 34, 38, 43, 72, 40, 51, 52, + 253, 106, 85, 79, 37, 80, 49, 51, 53, 54, + 43, 280, 265, 71, 55, 284, 3, 61, 38, 72, + 40, 8, 9, 76, 44, 137, 74, 93, 72, 49, + 74, 51, 74, 202, 44, 44, 71, 77, 82, 125, + 80, 61, 77, 88, 89, 71, 33, 34, 35, 36, + 37, 77, 72, 77, 74, 71, 76, 162, 71, 161, + 172, 77, 82, 70, 77, 72, 77, 43, 3, 80, + 72, 176, 79, 8, 9, 55, 56, 77, 161, 68, + 80, 125, 194, 74, 71, 254, 185, 186, 187, 188, + 37, 77, 204, 43, 80, 197, 85, 266, 33, 34, + 35, 36, 37, 92, 93, 125, 60, 61, 62, 80, + 286, 216, 217, 43, 197, 69, 285, 85, 86, 221, + 109, 4, 5, 6, 43, 79, 33, 34, 35, 70, + 70, 72, 71, 153, 77, 78, 183, 184, 221, 189, + 190, 253, 70, 57, 59, 40, 73, 72, 80, 80, + 70, 80, 70, 265, 70, 260, 77, 43, 75, 72, + 70, 273, 73, 75, 73, 73, 70, 73, 73, 70, + 16, 283, 161, 71, 71, 173, 191, 80, 80, 79, + 192, 286, 202, 82, 55, 193, 62, 5, 82, 250, + 210, 72, 181, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 198, 284, 210, 197, 53, + 265, 250, 44, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 250, -1, 221, 253, 254, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 265, 266, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 280, -1, -1, -1, 284, 285, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, -1, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, -1, -1, -1, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, -1, -1, 51, 52, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 70, -1, -1, -1, 74, 75, -1, + -1, -1, -1, 80, 81, 82, -1, 84, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, -1, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, + -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, -1, -1, 51, 52, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 70, -1, -1, -1, 74, + 75, -1, -1, -1, -1, 80, 81, 82, -1, 84, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, -1, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + -1, -1, -1, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, -1, -1, 51, 52, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 70, -1, -1, + -1, 74, -1, -1, -1, -1, -1, 80, 81, 82, + -1, 84, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, -1, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, -1, -1, -1, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, -1, -1, + 51, 52, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 70, + -1, -1, -1, 74, -1, -1, -1, -1, -1, 80, + 81, 82, -1, 84, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, -1, -1, -1, -1, -1, -1, + -1, -1, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, -1, -1, -1, 36, 37, 38, + 39, -1, 41, 42, 43, 44, 45, 46, 47, 48, + -1, -1, 51, 52, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 70, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 80, 81, 82, -1, 84, 3, 4, 5, 6, + -1, 8, 9, 10, 11, 12, -1, -1, -1, -1, + -1, -1, -1, -1, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, -1, -1, -1, 36, + 37, 38, 39, -1, 41, 42, 43, 44, 45, 46, + 47, 48, -1, -1, 51, 52, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 70, -1, -1, -1, 10, 11, 12, + -1, -1, -1, -1, 81, 82, -1, 84, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + -1, -1, -1, -1, -1, 38, 39, -1, 41, 42, + 43, 44, 45, 46, 47, 48, -1, -1, 51, 52, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 70, -1, -1, + 73, 10, 11, 12, -1, -1, -1, -1, 81, 82, + -1, 84, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, -1, -1, -1, -1, -1, 38, + 39, -1, 41, 42, 43, 44, 45, 46, 47, 48, + -1, -1, 51, 52, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 70, -1, -1, -1, 10, 11, 12, -1, -1, + -1, 80, 81, 82, -1, 84, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, + -1, -1, -1, 38, 39, -1, 41, 42, 43, 44, + 45, 46, 47, 48, -1, -1, 51, 52, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 70, -1, -1, 73, 10, + 11, 12, -1, -1, -1, -1, 81, 82, -1, 84, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, -1, -1, -1, -1, -1, 38, 39, -1, + 41, 42, 43, 44, 45, 46, 47, 48, -1, -1, + 51, 52, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 70, + -1, -1, -1, 10, 11, 12, -1, -1, -1, -1, + 81, 82, -1, 84, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, + -1, 38, 39, -1, 41, 42, 43, 44, 45, 46, + 47, 48, -1, -1, 51, 52, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 70, 4, 5, 6, -1, -1, -1, + 10, 11, 12, -1, 81, 82, -1, 84, -1, -1, + -1, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, -1, -1, -1, -1, -1, 38, 39, + -1, 41, 42, -1, 44, 4, 5, 6, -1, -1, + -1, 10, 11, 12, -1, -1, -1, -1, -1, -1, + -1, -1, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, -1, 75, -1, -1, -1, 38, + 39, -1, 41, 42, -1, 44, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 0, -1, -1, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, + -1, -1, -1, -1, -1, -1, 75, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, + -1, -1, 36, 37, 38, 39, -1, 41, 42, -1, + 44, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, -1, -1, -1, -1, -1, -1, -1, -1, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, -1, -1, -1, 36, 37, 38, 39, -1, 41, + 42, -1, 44, 4, 5, 6, -1, -1, -1, 10, + 11, 12, -1, -1, -1, -1, -1, -1, -1, -1, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, -1, 10, 11, 12, -1, 38, 39, -1, + 41, 42, -1, 44, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, + -1, 38, 39, -1, 41, 42, 43, 44, 10, 11, + 12, 48, -1, -1, -1, -1, -1, -1, -1, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, -1, -1, -1, -1, -1, 38, 39, -1, 41, + 42, -1, 44 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 36, 37, 38, 39, 41, 42, 44, + 124, 125, 126, 127, 128, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 168, 169, 170, 37, 43, 138, + 43, 74, 80, 171, 71, 77, 3, 33, 34, 35, + 130, 131, 136, 77, 80, 43, 137, 139, 72, 0, + 169, 139, 74, 137, 142, 143, 74, 154, 130, 129, + 132, 137, 131, 43, 70, 72, 79, 43, 45, 46, + 47, 48, 51, 52, 70, 81, 82, 84, 95, 96, + 97, 99, 100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, 119, 123, 140, 80, 142, 43, 144, 145, 75, + 143, 13, 14, 15, 17, 18, 19, 20, 40, 74, + 75, 80, 106, 119, 120, 122, 124, 125, 140, 147, + 148, 149, 150, 155, 156, 157, 160, 167, 43, 129, + 132, 72, 79, 73, 123, 120, 146, 106, 106, 122, + 51, 52, 72, 76, 71, 71, 77, 39, 120, 70, + 106, 85, 86, 82, 84, 53, 54, 88, 89, 55, + 56, 57, 59, 58, 93, 73, 75, 72, 77, 80, + 80, 80, 162, 70, 70, 80, 80, 122, 70, 75, + 151, 60, 61, 62, 69, 79, 121, 77, 80, 75, + 148, 72, 73, 123, 146, 73, 71, 98, 122, 43, + 48, 101, 120, 106, 106, 108, 108, 110, 110, 110, + 110, 111, 111, 115, 116, 117, 122, 123, 145, 148, + 163, 122, 80, 161, 155, 120, 120, 123, 73, 73, + 78, 73, 40, 147, 156, 164, 71, 122, 135, 159, + 152, 73, 120, 70, 159, 165, 166, 148, 158, 43, + 71, 75, 122, 80, 71, 16, 79, 149, 153, 154, + 71, 122, 153, 148, 146, 80 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (context, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, YYLEX_PARAM) +#else +# define YYLEX yylex (&yylval) +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value, context); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, TParseContext* context) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep, context) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; + TParseContext* context; +#endif +{ + if (!yyvaluep) + return; + YYUSE (context); +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, TParseContext* context) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep, context) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; + TParseContext* context; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep, context); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) +#else +static void +yy_stack_print (bottom, top) + yytype_int16 *bottom; + yytype_int16 *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule, TParseContext* context) +#else +static void +yy_reduce_print (yyvsp, yyrule, context) + YYSTYPE *yyvsp; + int yyrule; + TParseContext* context; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + fprintf (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + , context); + fprintf (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule, context); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, TParseContext* context) +#else +static void +yydestruct (yymsg, yytype, yyvaluep, context) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; + TParseContext* context; +#endif +{ + YYUSE (yyvaluep); + YYUSE (context); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (TParseContext* context); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (TParseContext* context) +#else +int +yyparse (context) + TParseContext* context; +#endif +#endif +{ + /* The look-ahead symbol. */ +int yychar; + +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + int yystate; + int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + look-ahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to look-ahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a look-ahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: + + { + // The symbol table search was done in the lexical phase + const TSymbol* symbol = (yyvsp[(1) - (1)].lex).symbol; + const TVariable* variable; + if (symbol == 0) { + context->error((yyvsp[(1) - (1)].lex).line, "undeclared identifier", (yyvsp[(1) - (1)].lex).string->c_str(), ""); + context->recover(); + TType type(EbtFloat, EbpUndefined); + TVariable* fakeVariable = new TVariable((yyvsp[(1) - (1)].lex).string, type); + context->symbolTable.insert(*fakeVariable); + variable = fakeVariable; + } else { + // This identifier can only be a variable type symbol + if (! symbol->isVariable()) { + context->error((yyvsp[(1) - (1)].lex).line, "variable expected", (yyvsp[(1) - (1)].lex).string->c_str(), ""); + context->recover(); + } + variable = static_cast<const TVariable*>(symbol); + } + + // don't delete $1.string, it's used by error recovery, and the pool + // pop will reclaim the memory + + if (variable->getType().getQualifier() == EvqConst ) { + ConstantUnion* constArray = variable->getConstPointer(); + TType t(variable->getType()); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(constArray, t, (yyvsp[(1) - (1)].lex).line); + } else + (yyval.interm.intermTypedNode) = context->intermediate.addSymbol(variable->getUniqueId(), + variable->getName(), + variable->getType(), (yyvsp[(1) - (1)].lex).line); + ;} + break; + + case 3: + + { + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); + ;} + break; + + case 4: + + { + // + // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders, + // check for overflow for constants + // + if (abs((yyvsp[(1) - (1)].lex).i) >= (1 << 16)) { + context->error((yyvsp[(1) - (1)].lex).line, " integer constant overflow", "", ""); + context->recover(); + } + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst((yyvsp[(1) - (1)].lex).i); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yyvsp[(1) - (1)].lex).line); + ;} + break; + + case 5: + + { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setFConst((yyvsp[(1) - (1)].lex).f); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), (yyvsp[(1) - (1)].lex).line); + ;} + break; + + case 6: + + { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst((yyvsp[(1) - (1)].lex).b); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(1) - (1)].lex).line); + ;} + break; + + case 7: + + { + (yyval.interm.intermTypedNode) = (yyvsp[(2) - (3)].interm.intermTypedNode); + ;} + break; + + case 8: + + { + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); + ;} + break; + + case 9: + + { + if (!(yyvsp[(1) - (4)].interm.intermTypedNode)->isArray() && !(yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix() && !(yyvsp[(1) - (4)].interm.intermTypedNode)->isVector()) { + if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode()) + context->error((yyvsp[(2) - (4)].lex).line, " left of '[' is not of type array, matrix, or vector ", (yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode()->getSymbol().c_str(), ""); + else + context->error((yyvsp[(2) - (4)].lex).line, " left of '[' is not of type array, matrix, or vector ", "expression", ""); + context->recover(); + } + if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConst && (yyvsp[(3) - (4)].interm.intermTypedNode)->getQualifier() == EvqConst) { + if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray()) { // constant folding for arrays + (yyval.interm.intermTypedNode) = context->addConstArrayNode((yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line); + } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector()) { // constant folding for vectors + TVectorFields fields; + fields.num = 1; + fields.offsets[0] = (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst(); // need to do it this way because v.xy sends fields integer array + (yyval.interm.intermTypedNode) = context->addConstVectorNode(fields, (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line); + } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix()) { // constant folding for matrices + (yyval.interm.intermTypedNode) = context->addConstMatrixNode((yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line); + } + } else { + if ((yyvsp[(3) - (4)].interm.intermTypedNode)->getQualifier() == EvqConst) { + if (((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector() || (yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix()) && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getNominalSize() <= (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst() && !(yyvsp[(1) - (4)].interm.intermTypedNode)->isArray() ) { + context->error((yyvsp[(2) - (4)].lex).line, "", "[", "field selection out of range '%d'", (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst()); + context->recover(); + } else { + if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray()) { + if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getArraySize() == 0) { + if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getMaxArraySize() <= (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst()) { + if (context->arraySetMaxSize((yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getTypePointer(), (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, (yyvsp[(2) - (4)].lex).line)) + context->recover(); + } else { + if (context->arraySetMaxSize((yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getTypePointer(), 0, false, (yyvsp[(2) - (4)].lex).line)) + context->recover(); + } + } else if ( (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getArraySize()) { + context->error((yyvsp[(2) - (4)].lex).line, "", "[", "array index out of range '%d'", (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst()); + context->recover(); + } + } + (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(3) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line); + } + } else { + if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray() && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getArraySize() == 0) { + context->error((yyvsp[(2) - (4)].lex).line, "", "[", "array must be redeclared with a size before being indexed with a variable"); + context->recover(); + } + + (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexIndirect, (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(3) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line); + } + } + if ((yyval.interm.intermTypedNode) == 0) { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setFConst(0.0f); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), (yyvsp[(2) - (4)].lex).line); + } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray()) { + if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getStruct()) + (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getStruct(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getTypeName())); + else + (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (yyvsp[(1) - (4)].interm.intermTypedNode)->getNominalSize(), (yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix())); + + if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) + (yyval.interm.intermTypedNode)->getTypePointer()->setQualifier(EvqConst); + } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix() && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) + (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqConst, (yyvsp[(1) - (4)].interm.intermTypedNode)->getNominalSize())); + else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix()) + (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (yyvsp[(1) - (4)].interm.intermTypedNode)->getNominalSize())); + else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector() && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) + (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqConst)); + else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector()) + (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqTemporary)); + else + (yyval.interm.intermTypedNode)->setType((yyvsp[(1) - (4)].interm.intermTypedNode)->getType()); + ;} + break; + + case 10: + + { + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); + ;} + break; + + case 11: + + { + if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isArray()) { + context->error((yyvsp[(3) - (3)].lex).line, "cannot apply dot operator to an array", ".", ""); + context->recover(); + } + + if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isVector()) { + TVectorFields fields; + if (! context->parseVectorFields(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize(), fields, (yyvsp[(3) - (3)].lex).line)) { + fields.num = 1; + fields.offsets[0] = 0; + context->recover(); + } + + if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) { // constant folding for vector fields + (yyval.interm.intermTypedNode) = context->addConstVectorNode(fields, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].lex).line); + if ((yyval.interm.intermTypedNode) == 0) { + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); + } + else + (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(), EvqConst, (int) (*(yyvsp[(3) - (3)].lex).string).size())); + } else { + if (fields.num == 1) { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(fields.offsets[0]); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yyvsp[(3) - (3)].lex).line); + (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line); + (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision())); + } else { + TString vectorString = *(yyvsp[(3) - (3)].lex).string; + TIntermTyped* index = context->intermediate.addSwizzle(fields, (yyvsp[(3) - (3)].lex).line); + (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpVectorSwizzle, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line); + (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (int) vectorString.size())); + } + } + } else if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isMatrix()) { + TMatrixFields fields; + if (! context->parseMatrixFields(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize(), fields, (yyvsp[(3) - (3)].lex).line)) { + fields.wholeRow = false; + fields.wholeCol = false; + fields.row = 0; + fields.col = 0; + context->recover(); + } + + if (fields.wholeRow || fields.wholeCol) { + context->error((yyvsp[(2) - (3)].lex).line, " non-scalar fields not implemented yet", ".", ""); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(0); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yyvsp[(3) - (3)].lex).line); + (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line); + (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(),EvqTemporary, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize())); + } else { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(fields.col * (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize() + fields.row); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yyvsp[(3) - (3)].lex).line); + (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line); + (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision())); + } + } else if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType() == EbtStruct) { + bool fieldFound = false; + const TTypeList* fields = (yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getStruct(); + if (fields == 0) { + context->error((yyvsp[(2) - (3)].lex).line, "structure has no fields", "Internal Error", ""); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); + } else { + unsigned int i; + for (i = 0; i < fields->size(); ++i) { + if ((*fields)[i].type->getFieldName() == *(yyvsp[(3) - (3)].lex).string) { + fieldFound = true; + break; + } + } + if (fieldFound) { + if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) { + (yyval.interm.intermTypedNode) = context->addConstStruct(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line); + if ((yyval.interm.intermTypedNode) == 0) { + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); + } + else { + (yyval.interm.intermTypedNode)->setType(*(*fields)[i].type); + // change the qualifier of the return type, not of the structure field + // as the structure definition is shared between various structures. + (yyval.interm.intermTypedNode)->getTypePointer()->setQualifier(EvqConst); + } + } else { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(i); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, (yyvsp[(3) - (3)].lex).line); + (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirectStruct, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line); + (yyval.interm.intermTypedNode)->setType(*(*fields)[i].type); + } + } else { + context->error((yyvsp[(2) - (3)].lex).line, " no such field in structure", (yyvsp[(3) - (3)].lex).string->c_str(), ""); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); + } + } + } else { + context->error((yyvsp[(2) - (3)].lex).line, " field selection requires structure, vector, or matrix on left hand side", (yyvsp[(3) - (3)].lex).string->c_str(), ""); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); + } + // don't delete $3.string, it's from the pool + ;} + break; + + case 12: + + { + if (context->lValueErrorCheck((yyvsp[(2) - (2)].lex).line, "++", (yyvsp[(1) - (2)].interm.intermTypedNode))) + context->recover(); + (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPostIncrement, (yyvsp[(1) - (2)].interm.intermTypedNode), (yyvsp[(2) - (2)].lex).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->unaryOpError((yyvsp[(2) - (2)].lex).line, "++", (yyvsp[(1) - (2)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (2)].interm.intermTypedNode); + } + ;} + break; + + case 13: + + { + if (context->lValueErrorCheck((yyvsp[(2) - (2)].lex).line, "--", (yyvsp[(1) - (2)].interm.intermTypedNode))) + context->recover(); + (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPostDecrement, (yyvsp[(1) - (2)].interm.intermTypedNode), (yyvsp[(2) - (2)].lex).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->unaryOpError((yyvsp[(2) - (2)].lex).line, "--", (yyvsp[(1) - (2)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (2)].interm.intermTypedNode); + } + ;} + break; + + case 14: + + { + if (context->integerErrorCheck((yyvsp[(1) - (1)].interm.intermTypedNode), "[]")) + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); + ;} + break; + + case 15: + + { + TFunction* fnCall = (yyvsp[(1) - (1)].interm).function; + TOperator op = fnCall->getBuiltInOp(); + + if (op != EOpNull) + { + // + // Then this should be a constructor. + // Don't go through the symbol table for constructors. + // Their parameters will be verified algorithmically. + // + TType type(EbtVoid, EbpUndefined); // use this to get the type back + if (context->constructorErrorCheck((yyvsp[(1) - (1)].interm).line, (yyvsp[(1) - (1)].interm).intermNode, *fnCall, op, &type)) { + (yyval.interm.intermTypedNode) = 0; + } else { + // + // It's a constructor, of type 'type'. + // + (yyval.interm.intermTypedNode) = context->addConstructor((yyvsp[(1) - (1)].interm).intermNode, &type, op, fnCall, (yyvsp[(1) - (1)].interm).line); + } + + if ((yyval.interm.intermTypedNode) == 0) { + context->recover(); + (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator(0, op, (yyvsp[(1) - (1)].interm).line); + } + (yyval.interm.intermTypedNode)->setType(type); + } else { + // + // Not a constructor. Find it in the symbol table. + // + const TFunction* fnCandidate; + bool builtIn; + fnCandidate = context->findFunction((yyvsp[(1) - (1)].interm).line, fnCall, &builtIn); + if (fnCandidate) { + // + // A declared function. + // + if (builtIn && !fnCandidate->getExtension().empty() && + context->extensionErrorCheck((yyvsp[(1) - (1)].interm).line, fnCandidate->getExtension())) { + context->recover(); + } + op = fnCandidate->getBuiltInOp(); + if (builtIn && op != EOpNull) { + // + // A function call mapped to a built-in operation. + // + if (fnCandidate->getParamCount() == 1) { + // + // Treat it like a built-in unary operator. + // + (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(op, (yyvsp[(1) - (1)].interm).intermNode, 0, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->error((yyvsp[(1) - (1)].interm).intermNode->getLine(), " wrong operand type", "Internal Error", + "built in unary operator function. Type: %s", + static_cast<TIntermTyped*>((yyvsp[(1) - (1)].interm).intermNode)->getCompleteString().c_str()); + YYERROR; + } + } else { + (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator((yyvsp[(1) - (1)].interm).intermAggregate, op, (yyvsp[(1) - (1)].interm).line); + } + } else { + // This is a real function call + + (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator((yyvsp[(1) - (1)].interm).intermAggregate, EOpFunctionCall, (yyvsp[(1) - (1)].interm).line); + (yyval.interm.intermTypedNode)->setType(fnCandidate->getReturnType()); + + // this is how we know whether the given function is a builtIn function or a user defined function + // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also + // if builtIn == true, it's definitely a builtIn function with EOpNull + if (!builtIn) + (yyval.interm.intermTypedNode)->getAsAggregate()->setUserDefined(); + (yyval.interm.intermTypedNode)->getAsAggregate()->setName(fnCandidate->getMangledName()); + + TQualifier qual; + for (int i = 0; i < fnCandidate->getParamCount(); ++i) { + qual = fnCandidate->getParam(i).type->getQualifier(); + if (qual == EvqOut || qual == EvqInOut) { + if (context->lValueErrorCheck((yyval.interm.intermTypedNode)->getLine(), "assign", (yyval.interm.intermTypedNode)->getAsAggregate()->getSequence()[i]->getAsTyped())) { + context->error((yyvsp[(1) - (1)].interm).intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", ""); + context->recover(); + } + } + } + } + (yyval.interm.intermTypedNode)->setType(fnCandidate->getReturnType()); + } else { + // error message was put out by PaFindFunction() + // Put on a dummy node for error recovery + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setFConst(0.0f); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), (yyvsp[(1) - (1)].interm).line); + context->recover(); + } + } + delete fnCall; + ;} + break; + + case 16: + + { + (yyval.interm) = (yyvsp[(1) - (1)].interm); + ;} + break; + + case 17: + + { + context->error((yyvsp[(3) - (3)].interm).line, "methods are not supported", "", ""); + context->recover(); + (yyval.interm) = (yyvsp[(3) - (3)].interm); + ;} + break; + + case 18: + + { + (yyval.interm) = (yyvsp[(1) - (2)].interm); + (yyval.interm).line = (yyvsp[(2) - (2)].lex).line; + ;} + break; + + case 19: + + { + (yyval.interm) = (yyvsp[(1) - (2)].interm); + (yyval.interm).line = (yyvsp[(2) - (2)].lex).line; + ;} + break; + + case 20: + + { + (yyval.interm).function = (yyvsp[(1) - (2)].interm.function); + (yyval.interm).intermNode = 0; + ;} + break; + + case 21: + + { + (yyval.interm).function = (yyvsp[(1) - (1)].interm.function); + (yyval.interm).intermNode = 0; + ;} + break; + + case 22: + + { + TParameter param = { 0, new TType((yyvsp[(2) - (2)].interm.intermTypedNode)->getType()) }; + (yyvsp[(1) - (2)].interm.function)->addParameter(param); + (yyval.interm).function = (yyvsp[(1) - (2)].interm.function); + (yyval.interm).intermNode = (yyvsp[(2) - (2)].interm.intermTypedNode); + ;} + break; + + case 23: + + { + TParameter param = { 0, new TType((yyvsp[(3) - (3)].interm.intermTypedNode)->getType()) }; + (yyvsp[(1) - (3)].interm).function->addParameter(param); + (yyval.interm).function = (yyvsp[(1) - (3)].interm).function; + (yyval.interm).intermNode = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermNode, (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line); + ;} + break; + + case 24: + + { + (yyval.interm.function) = (yyvsp[(1) - (2)].interm.function); + ;} + break; + + case 25: + + { + // + // Constructor + // + TOperator op = EOpNull; + if ((yyvsp[(1) - (1)].interm.type).userDef) { + op = EOpConstructStruct; + } else { + switch ((yyvsp[(1) - (1)].interm.type).type) { + case EbtFloat: + if ((yyvsp[(1) - (1)].interm.type).matrix) { + switch((yyvsp[(1) - (1)].interm.type).size) { + case 2: op = EOpConstructMat2; break; + case 3: op = EOpConstructMat3; break; + case 4: op = EOpConstructMat4; break; + } + } else { + switch((yyvsp[(1) - (1)].interm.type).size) { + case 1: op = EOpConstructFloat; break; + case 2: op = EOpConstructVec2; break; + case 3: op = EOpConstructVec3; break; + case 4: op = EOpConstructVec4; break; + } + } + break; + case EbtInt: + switch((yyvsp[(1) - (1)].interm.type).size) { + case 1: op = EOpConstructInt; break; + case 2: FRAG_VERT_ONLY("ivec2", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructIVec2; break; + case 3: FRAG_VERT_ONLY("ivec3", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructIVec3; break; + case 4: FRAG_VERT_ONLY("ivec4", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructIVec4; break; + } + break; + case EbtBool: + switch((yyvsp[(1) - (1)].interm.type).size) { + case 1: op = EOpConstructBool; break; + case 2: FRAG_VERT_ONLY("bvec2", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructBVec2; break; + case 3: FRAG_VERT_ONLY("bvec3", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructBVec3; break; + case 4: FRAG_VERT_ONLY("bvec4", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructBVec4; break; + } + break; + default: break; + } + if (op == EOpNull) { + context->error((yyvsp[(1) - (1)].interm.type).line, "cannot construct this type", getBasicString((yyvsp[(1) - (1)].interm.type).type), ""); + context->recover(); + (yyvsp[(1) - (1)].interm.type).type = EbtFloat; + op = EOpConstructFloat; + } + } + TString tempString; + TType type((yyvsp[(1) - (1)].interm.type)); + TFunction *function = new TFunction(&tempString, type, op); + (yyval.interm.function) = function; + ;} + break; + + case 26: + + { + if (context->reservedErrorCheck((yyvsp[(1) - (1)].lex).line, *(yyvsp[(1) - (1)].lex).string)) + context->recover(); + TType type(EbtVoid, EbpUndefined); + TFunction *function = new TFunction((yyvsp[(1) - (1)].lex).string, type); + (yyval.interm.function) = function; + ;} + break; + + case 27: + + { + if (context->reservedErrorCheck((yyvsp[(1) - (1)].lex).line, *(yyvsp[(1) - (1)].lex).string)) + context->recover(); + TType type(EbtVoid, EbpUndefined); + TFunction *function = new TFunction((yyvsp[(1) - (1)].lex).string, type); + (yyval.interm.function) = function; + ;} + break; + + case 28: + + { + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); + ;} + break; + + case 29: + + { + if (context->lValueErrorCheck((yyvsp[(1) - (2)].lex).line, "++", (yyvsp[(2) - (2)].interm.intermTypedNode))) + context->recover(); + (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPreIncrement, (yyvsp[(2) - (2)].interm.intermTypedNode), (yyvsp[(1) - (2)].lex).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->unaryOpError((yyvsp[(1) - (2)].lex).line, "++", (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode); + } + ;} + break; + + case 30: + + { + if (context->lValueErrorCheck((yyvsp[(1) - (2)].lex).line, "--", (yyvsp[(2) - (2)].interm.intermTypedNode))) + context->recover(); + (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPreDecrement, (yyvsp[(2) - (2)].interm.intermTypedNode), (yyvsp[(1) - (2)].lex).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->unaryOpError((yyvsp[(1) - (2)].lex).line, "--", (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode); + } + ;} + break; + + case 31: + + { + if ((yyvsp[(1) - (2)].interm).op != EOpNull) { + (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath((yyvsp[(1) - (2)].interm).op, (yyvsp[(2) - (2)].interm.intermTypedNode), (yyvsp[(1) - (2)].interm).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + const char* errorOp = ""; + switch((yyvsp[(1) - (2)].interm).op) { + case EOpNegative: errorOp = "-"; break; + case EOpLogicalNot: errorOp = "!"; break; + default: break; + } + context->unaryOpError((yyvsp[(1) - (2)].interm).line, errorOp, (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode); + } + } else + (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode); + ;} + break; + + case 32: + + { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpNull; ;} + break; + + case 33: + + { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpNegative; ;} + break; + + case 34: + + { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpLogicalNot; ;} + break; + + case 35: + + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;} + break; + + case 36: + + { + FRAG_VERT_ONLY("*", (yyvsp[(2) - (3)].lex).line); + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpMul, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yyvsp[(2) - (3)].lex).line, "*", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); + } + ;} + break; + + case 37: + + { + FRAG_VERT_ONLY("/", (yyvsp[(2) - (3)].lex).line); + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpDiv, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yyvsp[(2) - (3)].lex).line, "/", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); + } + ;} + break; + + case 38: + + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;} + break; + + case 39: + + { + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpAdd, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yyvsp[(2) - (3)].lex).line, "+", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); + } + ;} + break; + + case 40: + + { + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpSub, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yyvsp[(2) - (3)].lex).line, "-", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); + } + ;} + break; + + case 41: + + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;} + break; + + case 42: + + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;} + break; + + case 43: + + { + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLessThan, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yyvsp[(2) - (3)].lex).line, "<", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); + } + ;} + break; + + case 44: + + { + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpGreaterThan, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yyvsp[(2) - (3)].lex).line, ">", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); + } + ;} + break; + + case 45: + + { + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLessThanEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yyvsp[(2) - (3)].lex).line, "<=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); + } + ;} + break; + + case 46: + + { + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpGreaterThanEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yyvsp[(2) - (3)].lex).line, ">=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); + } + ;} + break; + + case 47: + + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;} + break; + + case 48: + + { + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yyvsp[(2) - (3)].lex).line, "==", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); + } + ;} + break; + + case 49: + + { + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpNotEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yyvsp[(2) - (3)].lex).line, "!=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); + } + ;} + break; + + case 50: + + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;} + break; + + case 51: + + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;} + break; + + case 52: + + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;} + break; + + case 53: + + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;} + break; + + case 54: + + { + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalAnd, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yyvsp[(2) - (3)].lex).line, "&&", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); + } + ;} + break; + + case 55: + + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;} + break; + + case 56: + + { + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalXor, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yyvsp[(2) - (3)].lex).line, "^^", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); + } + ;} + break; + + case 57: + + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;} + break; + + case 58: + + { + (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalOr, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yyvsp[(2) - (3)].lex).line, "||", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line); + } + ;} + break; + + case 59: + + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;} + break; + + case 60: + + { + if (context->boolErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(1) - (5)].interm.intermTypedNode))) + context->recover(); + + (yyval.interm.intermTypedNode) = context->intermediate.addSelection((yyvsp[(1) - (5)].interm.intermTypedNode), (yyvsp[(3) - (5)].interm.intermTypedNode), (yyvsp[(5) - (5)].interm.intermTypedNode), (yyvsp[(2) - (5)].lex).line); + if ((yyvsp[(3) - (5)].interm.intermTypedNode)->getType() != (yyvsp[(5) - (5)].interm.intermTypedNode)->getType()) + (yyval.interm.intermTypedNode) = 0; + + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yyvsp[(2) - (5)].lex).line, ":", (yyvsp[(3) - (5)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(5) - (5)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(5) - (5)].interm.intermTypedNode); + } + ;} + break; + + case 61: + + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;} + break; + + case 62: + + { + if (context->lValueErrorCheck((yyvsp[(2) - (3)].interm).line, "assign", (yyvsp[(1) - (3)].interm.intermTypedNode))) + context->recover(); + (yyval.interm.intermTypedNode) = context->intermediate.addAssign((yyvsp[(2) - (3)].interm).op, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].interm).line); + if ((yyval.interm.intermTypedNode) == 0) { + context->assignError((yyvsp[(2) - (3)].interm).line, "assign", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode); + } + ;} + break; + + case 63: + + { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpAssign; ;} + break; + + case 64: + + { FRAG_VERT_ONLY("*=", (yyvsp[(1) - (1)].lex).line); (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpMulAssign; ;} + break; + + case 65: + + { FRAG_VERT_ONLY("/=", (yyvsp[(1) - (1)].lex).line); (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpDivAssign; ;} + break; + + case 66: + + { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpAddAssign; ;} + break; + + case 67: + + { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpSubAssign; ;} + break; + + case 68: + + { + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); + ;} + break; + + case 69: + + { + (yyval.interm.intermTypedNode) = context->intermediate.addComma((yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line); + if ((yyval.interm.intermTypedNode) == 0) { + context->binaryOpError((yyvsp[(2) - (3)].lex).line, ",", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString()); + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(3) - (3)].interm.intermTypedNode); + } + ;} + break; + + case 70: + + { + if (context->constErrorCheck((yyvsp[(1) - (1)].interm.intermTypedNode))) + context->recover(); + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); + ;} + break; + + case 71: + + { + TFunction &function = *((yyvsp[(1) - (2)].interm).function); + + TIntermAggregate *prototype = new TIntermAggregate; + prototype->setType(function.getReturnType()); + prototype->setName(function.getName()); + + for (int i = 0; i < function.getParamCount(); i++) + { + const TParameter ¶m = function.getParam(i); + if (param.name != 0) + { + TVariable *variable = new TVariable(param.name, *param.type); + + prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), (yyvsp[(1) - (2)].interm).line), (yyvsp[(1) - (2)].interm).line); + } + else + { + prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, (yyvsp[(1) - (2)].interm).line), (yyvsp[(1) - (2)].interm).line); + } + } + + prototype->setOp(EOpPrototype); + (yyval.interm.intermNode) = prototype; + ;} + break; + + case 72: + + { + if ((yyvsp[(1) - (2)].interm).intermAggregate) + (yyvsp[(1) - (2)].interm).intermAggregate->setOp(EOpDeclaration); + (yyval.interm.intermNode) = (yyvsp[(1) - (2)].interm).intermAggregate; + ;} + break; + + case 73: + + { + context->symbolTable.setDefaultPrecision( (yyvsp[(3) - (4)].interm.type).type, (yyvsp[(2) - (4)].interm.precision) ); + (yyval.interm.intermNode) = 0; + ;} + break; + + case 74: + + { + // + // Multiple declarations of the same function are allowed. + // + // If this is a definition, the definition production code will check for redefinitions + // (we don't know at this point if it's a definition or not). + // + // Redeclarations are allowed. But, return types and parameter qualifiers must match. + // + TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find((yyvsp[(1) - (2)].interm.function)->getMangledName())); + if (prevDec) { + if (prevDec->getReturnType() != (yyvsp[(1) - (2)].interm.function)->getReturnType()) { + context->error((yyvsp[(2) - (2)].lex).line, "overloaded functions must have the same return type", (yyvsp[(1) - (2)].interm.function)->getReturnType().getBasicString(), ""); + context->recover(); + } + for (int i = 0; i < prevDec->getParamCount(); ++i) { + if (prevDec->getParam(i).type->getQualifier() != (yyvsp[(1) - (2)].interm.function)->getParam(i).type->getQualifier()) { + context->error((yyvsp[(2) - (2)].lex).line, "overloaded functions must have the same parameter qualifiers", (yyvsp[(1) - (2)].interm.function)->getParam(i).type->getQualifierString(), ""); + context->recover(); + } + } + } + + // + // If this is a redeclaration, it could also be a definition, + // in which case, we want to use the variable names from this one, and not the one that's + // being redeclared. So, pass back up this declaration, not the one in the symbol table. + // + (yyval.interm).function = (yyvsp[(1) - (2)].interm.function); + (yyval.interm).line = (yyvsp[(2) - (2)].lex).line; + + context->symbolTable.insert(*(yyval.interm).function); + ;} + break; + + case 75: + + { + (yyval.interm.function) = (yyvsp[(1) - (1)].interm.function); + ;} + break; + + case 76: + + { + (yyval.interm.function) = (yyvsp[(1) - (1)].interm.function); + ;} + break; + + case 77: + + { + // Add the parameter + (yyval.interm.function) = (yyvsp[(1) - (2)].interm.function); + if ((yyvsp[(2) - (2)].interm).param.type->getBasicType() != EbtVoid) + (yyvsp[(1) - (2)].interm.function)->addParameter((yyvsp[(2) - (2)].interm).param); + else + delete (yyvsp[(2) - (2)].interm).param.type; + ;} + break; + + case 78: + + { + // + // Only first parameter of one-parameter functions can be void + // The check for named parameters not being void is done in parameter_declarator + // + if ((yyvsp[(3) - (3)].interm).param.type->getBasicType() == EbtVoid) { + // + // This parameter > first is void + // + context->error((yyvsp[(2) - (3)].lex).line, "cannot be an argument type except for '(void)'", "void", ""); + context->recover(); + delete (yyvsp[(3) - (3)].interm).param.type; + } else { + // Add the parameter + (yyval.interm.function) = (yyvsp[(1) - (3)].interm.function); + (yyvsp[(1) - (3)].interm.function)->addParameter((yyvsp[(3) - (3)].interm).param); + } + ;} + break; + + case 79: + + { + if ((yyvsp[(1) - (3)].interm.type).qualifier != EvqGlobal && (yyvsp[(1) - (3)].interm.type).qualifier != EvqTemporary) { + context->error((yyvsp[(2) - (3)].lex).line, "no qualifiers allowed for function return", getQualifierString((yyvsp[(1) - (3)].interm.type).qualifier), ""); + context->recover(); + } + // make sure a sampler is not involved as well... + if (context->structQualifierErrorCheck((yyvsp[(2) - (3)].lex).line, (yyvsp[(1) - (3)].interm.type))) + context->recover(); + + // Add the function as a prototype after parsing it (we do not support recursion) + TFunction *function; + TType type((yyvsp[(1) - (3)].interm.type)); + function = new TFunction((yyvsp[(2) - (3)].lex).string, type); + (yyval.interm.function) = function; + ;} + break; + + case 80: + + { + if ((yyvsp[(1) - (2)].interm.type).type == EbtVoid) { + context->error((yyvsp[(2) - (2)].lex).line, "illegal use of type 'void'", (yyvsp[(2) - (2)].lex).string->c_str(), ""); + context->recover(); + } + if (context->reservedErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string)) + context->recover(); + TParameter param = {(yyvsp[(2) - (2)].lex).string, new TType((yyvsp[(1) - (2)].interm.type))}; + (yyval.interm).line = (yyvsp[(2) - (2)].lex).line; + (yyval.interm).param = param; + ;} + break; + + case 81: + + { + // Check that we can make an array out of this type + if (context->arrayTypeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type))) + context->recover(); + + if (context->reservedErrorCheck((yyvsp[(2) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string)) + context->recover(); + + int size; + if (context->arraySizeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode), size)) + context->recover(); + (yyvsp[(1) - (5)].interm.type).setArray(true, size); + + TType* type = new TType((yyvsp[(1) - (5)].interm.type)); + TParameter param = { (yyvsp[(2) - (5)].lex).string, type }; + (yyval.interm).line = (yyvsp[(2) - (5)].lex).line; + (yyval.interm).param = param; + ;} + break; + + case 82: + + { + (yyval.interm) = (yyvsp[(3) - (3)].interm); + if (context->paramErrorCheck((yyvsp[(3) - (3)].interm).line, (yyvsp[(1) - (3)].interm.type).qualifier, (yyvsp[(2) - (3)].interm.qualifier), (yyval.interm).param.type)) + context->recover(); + ;} + break; + + case 83: + + { + (yyval.interm) = (yyvsp[(2) - (2)].interm); + if (context->parameterSamplerErrorCheck((yyvsp[(2) - (2)].interm).line, (yyvsp[(1) - (2)].interm.qualifier), *(yyvsp[(2) - (2)].interm).param.type)) + context->recover(); + if (context->paramErrorCheck((yyvsp[(2) - (2)].interm).line, EvqTemporary, (yyvsp[(1) - (2)].interm.qualifier), (yyval.interm).param.type)) + context->recover(); + ;} + break; + + case 84: + + { + (yyval.interm) = (yyvsp[(3) - (3)].interm); + if (context->paramErrorCheck((yyvsp[(3) - (3)].interm).line, (yyvsp[(1) - (3)].interm.type).qualifier, (yyvsp[(2) - (3)].interm.qualifier), (yyval.interm).param.type)) + context->recover(); + ;} + break; + + case 85: + + { + (yyval.interm) = (yyvsp[(2) - (2)].interm); + if (context->parameterSamplerErrorCheck((yyvsp[(2) - (2)].interm).line, (yyvsp[(1) - (2)].interm.qualifier), *(yyvsp[(2) - (2)].interm).param.type)) + context->recover(); + if (context->paramErrorCheck((yyvsp[(2) - (2)].interm).line, EvqTemporary, (yyvsp[(1) - (2)].interm.qualifier), (yyval.interm).param.type)) + context->recover(); + ;} + break; + + case 86: + + { + (yyval.interm.qualifier) = EvqIn; + ;} + break; + + case 87: + + { + (yyval.interm.qualifier) = EvqIn; + ;} + break; + + case 88: + + { + (yyval.interm.qualifier) = EvqOut; + ;} + break; + + case 89: + + { + (yyval.interm.qualifier) = EvqInOut; + ;} + break; + + case 90: + + { + TParameter param = { 0, new TType((yyvsp[(1) - (1)].interm.type)) }; + (yyval.interm).param = param; + ;} + break; + + case 91: + + { + (yyval.interm) = (yyvsp[(1) - (1)].interm); + ;} + break; + + case 92: + + { + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(3) - (3)].lex).string, TType((yyvsp[(1) - (3)].interm).type), (yyvsp[(3) - (3)].lex).line); + (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermNode, symbol, (yyvsp[(3) - (3)].lex).line); + + if (context->structQualifierErrorCheck((yyvsp[(3) - (3)].lex).line, (yyval.interm).type)) + context->recover(); + + if (context->nonInitConstErrorCheck((yyvsp[(3) - (3)].lex).line, *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type)) + context->recover(); + + TVariable* variable = 0; + if (context->nonInitErrorCheck((yyvsp[(3) - (3)].lex).line, *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type, variable)) + context->recover(); + if (symbol && variable) + symbol->setId(variable->getUniqueId()); + ;} + break; + + case 93: + + { + if (context->structQualifierErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type)) + context->recover(); + + if (context->nonInitConstErrorCheck((yyvsp[(3) - (5)].lex).line, *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type)) + context->recover(); + + (yyval.interm) = (yyvsp[(1) - (5)].interm); + + if (context->arrayTypeErrorCheck((yyvsp[(4) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type) || context->arrayQualifierErrorCheck((yyvsp[(4) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type)) + context->recover(); + else { + (yyvsp[(1) - (5)].interm).type.setArray(true); + TVariable* variable; + if (context->arrayErrorCheck((yyvsp[(4) - (5)].lex).line, *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, variable)) + context->recover(); + } + ;} + break; + + case 94: + + { + if (context->structQualifierErrorCheck((yyvsp[(3) - (6)].lex).line, (yyvsp[(1) - (6)].interm).type)) + context->recover(); + + if (context->nonInitConstErrorCheck((yyvsp[(3) - (6)].lex).line, *(yyvsp[(3) - (6)].lex).string, (yyvsp[(1) - (6)].interm).type)) + context->recover(); + + (yyval.interm) = (yyvsp[(1) - (6)].interm); + + if (context->arrayTypeErrorCheck((yyvsp[(4) - (6)].lex).line, (yyvsp[(1) - (6)].interm).type) || context->arrayQualifierErrorCheck((yyvsp[(4) - (6)].lex).line, (yyvsp[(1) - (6)].interm).type)) + context->recover(); + else { + int size; + if (context->arraySizeErrorCheck((yyvsp[(4) - (6)].lex).line, (yyvsp[(5) - (6)].interm.intermTypedNode), size)) + context->recover(); + (yyvsp[(1) - (6)].interm).type.setArray(true, size); + TVariable* variable = 0; + if (context->arrayErrorCheck((yyvsp[(4) - (6)].lex).line, *(yyvsp[(3) - (6)].lex).string, (yyvsp[(1) - (6)].interm).type, variable)) + context->recover(); + TType type = TType((yyvsp[(1) - (6)].interm).type); + type.setArraySize(size); + (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (6)].interm).intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *(yyvsp[(3) - (6)].lex).string, type, (yyvsp[(3) - (6)].lex).line), (yyvsp[(3) - (6)].lex).line); + } + ;} + break; + + case 95: + + { + if (context->structQualifierErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type)) + context->recover(); + + (yyval.interm) = (yyvsp[(1) - (5)].interm); + + TIntermNode* intermNode; + if (!context->executeInitializer((yyvsp[(3) - (5)].lex).line, *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, (yyvsp[(5) - (5)].interm.intermTypedNode), intermNode)) { + // + // build the intermediate representation + // + if (intermNode) + (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (5)].interm).intermNode, intermNode, (yyvsp[(4) - (5)].lex).line); + else + (yyval.interm).intermAggregate = (yyvsp[(1) - (5)].interm).intermAggregate; + } else { + context->recover(); + (yyval.interm).intermAggregate = 0; + } + ;} + break; + + case 96: + + { + (yyval.interm).type = (yyvsp[(1) - (1)].interm.type); + (yyval.interm).intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType((yyvsp[(1) - (1)].interm.type)), (yyvsp[(1) - (1)].interm.type).line), (yyvsp[(1) - (1)].interm.type).line); + ;} + break; + + case 97: + + { + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (2)].lex).string, TType((yyvsp[(1) - (2)].interm.type)), (yyvsp[(2) - (2)].lex).line); + (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (2)].lex).line); + + if (context->structQualifierErrorCheck((yyvsp[(2) - (2)].lex).line, (yyval.interm).type)) + context->recover(); + + if (context->nonInitConstErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type)) + context->recover(); + + (yyval.interm).type = (yyvsp[(1) - (2)].interm.type); + + TVariable* variable = 0; + if (context->nonInitErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, variable)) + context->recover(); + if (variable && symbol) + symbol->setId(variable->getUniqueId()); + ;} + break; + + case 98: + + { + context->error((yyvsp[(2) - (4)].lex).line, "unsized array declarations not supported", (yyvsp[(2) - (4)].lex).string->c_str(), ""); + context->recover(); + + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (4)].lex).string, TType((yyvsp[(1) - (4)].interm.type)), (yyvsp[(2) - (4)].lex).line); + (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (4)].lex).line); + (yyval.interm).type = (yyvsp[(1) - (4)].interm.type); + ;} + break; + + case 99: + + { + TType type = TType((yyvsp[(1) - (5)].interm.type)); + int size; + if (context->arraySizeErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode), size)) + context->recover(); + type.setArraySize(size); + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (5)].lex).string, type, (yyvsp[(2) - (5)].lex).line); + (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (5)].lex).line); + + if (context->structQualifierErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type))) + context->recover(); + + if (context->nonInitConstErrorCheck((yyvsp[(2) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type))) + context->recover(); + + (yyval.interm).type = (yyvsp[(1) - (5)].interm.type); + + if (context->arrayTypeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)) || context->arrayQualifierErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type))) + context->recover(); + else { + int size; + if (context->arraySizeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode), size)) + context->recover(); + + (yyvsp[(1) - (5)].interm.type).setArray(true, size); + TVariable* variable = 0; + if (context->arrayErrorCheck((yyvsp[(3) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), variable)) + context->recover(); + if (variable && symbol) + symbol->setId(variable->getUniqueId()); + } + ;} + break; + + case 100: + + { + if (context->structQualifierErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type))) + context->recover(); + + (yyval.interm).type = (yyvsp[(1) - (4)].interm.type); + + TIntermNode* intermNode; + if (!context->executeInitializer((yyvsp[(2) - (4)].lex).line, *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), (yyvsp[(4) - (4)].interm.intermTypedNode), intermNode)) { + // + // Build intermediate representation + // + if(intermNode) + (yyval.interm).intermAggregate = context->intermediate.makeAggregate(intermNode, (yyvsp[(3) - (4)].lex).line); + else + (yyval.interm).intermAggregate = 0; + } else { + context->recover(); + (yyval.interm).intermAggregate = 0; + } + ;} + break; + + case 101: + + { + VERTEX_ONLY("invariant declaration", (yyvsp[(1) - (2)].lex).line); + (yyval.interm).qualifier = EvqInvariantVaryingOut; + (yyval.interm).intermAggregate = 0; + ;} + break; + + case 102: + + { + (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type); + + if ((yyvsp[(1) - (1)].interm.type).array) { + context->error((yyvsp[(1) - (1)].interm.type).line, "not supported", "first-class array", ""); + context->recover(); + (yyvsp[(1) - (1)].interm.type).setArray(false); + } + ;} + break; + + case 103: + + { + if ((yyvsp[(2) - (2)].interm.type).array) { + context->error((yyvsp[(2) - (2)].interm.type).line, "not supported", "first-class array", ""); + context->recover(); + (yyvsp[(2) - (2)].interm.type).setArray(false); + } + + if ((yyvsp[(1) - (2)].interm.type).qualifier == EvqAttribute && + ((yyvsp[(2) - (2)].interm.type).type == EbtBool || (yyvsp[(2) - (2)].interm.type).type == EbtInt)) { + context->error((yyvsp[(2) - (2)].interm.type).line, "cannot be bool or int", getQualifierString((yyvsp[(1) - (2)].interm.type).qualifier), ""); + context->recover(); + } + if (((yyvsp[(1) - (2)].interm.type).qualifier == EvqVaryingIn || (yyvsp[(1) - (2)].interm.type).qualifier == EvqVaryingOut) && + ((yyvsp[(2) - (2)].interm.type).type == EbtBool || (yyvsp[(2) - (2)].interm.type).type == EbtInt)) { + context->error((yyvsp[(2) - (2)].interm.type).line, "cannot be bool or int", getQualifierString((yyvsp[(1) - (2)].interm.type).qualifier), ""); + context->recover(); + } + (yyval.interm.type) = (yyvsp[(2) - (2)].interm.type); + (yyval.interm.type).qualifier = (yyvsp[(1) - (2)].interm.type).qualifier; + ;} + break; + + case 104: + + { + (yyval.interm.type).setBasic(EbtVoid, EvqConst, (yyvsp[(1) - (1)].lex).line); + ;} + break; + + case 105: + + { + VERTEX_ONLY("attribute", (yyvsp[(1) - (1)].lex).line); + if (context->globalErrorCheck((yyvsp[(1) - (1)].lex).line, context->symbolTable.atGlobalLevel(), "attribute")) + context->recover(); + (yyval.interm.type).setBasic(EbtVoid, EvqAttribute, (yyvsp[(1) - (1)].lex).line); + ;} + break; + + case 106: + + { + if (context->globalErrorCheck((yyvsp[(1) - (1)].lex).line, context->symbolTable.atGlobalLevel(), "varying")) + context->recover(); + if (context->shaderType == SH_VERTEX_SHADER) + (yyval.interm.type).setBasic(EbtVoid, EvqVaryingOut, (yyvsp[(1) - (1)].lex).line); + else + (yyval.interm.type).setBasic(EbtVoid, EvqVaryingIn, (yyvsp[(1) - (1)].lex).line); + ;} + break; + + case 107: + + { + if (context->globalErrorCheck((yyvsp[(1) - (2)].lex).line, context->symbolTable.atGlobalLevel(), "invariant varying")) + context->recover(); + if (context->shaderType == SH_VERTEX_SHADER) + (yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingOut, (yyvsp[(1) - (2)].lex).line); + else + (yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingIn, (yyvsp[(1) - (2)].lex).line); + ;} + break; + + case 108: + + { + if (context->globalErrorCheck((yyvsp[(1) - (1)].lex).line, context->symbolTable.atGlobalLevel(), "uniform")) + context->recover(); + (yyval.interm.type).setBasic(EbtVoid, EvqUniform, (yyvsp[(1) - (1)].lex).line); + ;} + break; + + case 109: + + { + (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type); + + if ((yyval.interm.type).precision == EbpUndefined) { + (yyval.interm.type).precision = context->symbolTable.getDefaultPrecision((yyvsp[(1) - (1)].interm.type).type); + if (context->precisionErrorCheck((yyvsp[(1) - (1)].interm.type).line, (yyval.interm.type).precision, (yyvsp[(1) - (1)].interm.type).type)) { + context->recover(); + } + } + ;} + break; + + case 110: + + { + (yyval.interm.type) = (yyvsp[(2) - (2)].interm.type); + (yyval.interm.type).precision = (yyvsp[(1) - (2)].interm.precision); + ;} + break; + + case 111: + + { + (yyval.interm.precision) = EbpHigh; + ;} + break; + + case 112: + + { + (yyval.interm.precision) = EbpMedium; + ;} + break; + + case 113: + + { + (yyval.interm.precision) = EbpLow; + ;} + break; + + case 114: + + { + (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type); + ;} + break; + + case 115: + + { + (yyval.interm.type) = (yyvsp[(1) - (4)].interm.type); + + if (context->arrayTypeErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type))) + context->recover(); + else { + int size; + if (context->arraySizeErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(3) - (4)].interm.intermTypedNode), size)) + context->recover(); + (yyval.interm.type).setArray(true, size); + } + ;} + break; + + case 116: + + { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtVoid, qual, (yyvsp[(1) - (1)].lex).line); + ;} + break; + + case 117: + + { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line); + ;} + break; + + case 118: + + { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtInt, qual, (yyvsp[(1) - (1)].lex).line); + ;} + break; + + case 119: + + { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtBool, qual, (yyvsp[(1) - (1)].lex).line); + ;} + break; + + case 120: + + { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setAggregate(2); + ;} + break; + + case 121: + + { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setAggregate(3); + ;} + break; + + case 122: + + { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setAggregate(4); + ;} + break; + + case 123: + + { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtBool, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setAggregate(2); + ;} + break; + + case 124: + + { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtBool, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setAggregate(3); + ;} + break; + + case 125: + + { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtBool, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setAggregate(4); + ;} + break; + + case 126: + + { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtInt, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setAggregate(2); + ;} + break; + + case 127: + + { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtInt, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setAggregate(3); + ;} + break; + + case 128: + + { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtInt, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setAggregate(4); + ;} + break; + + case 129: + + { + FRAG_VERT_ONLY("mat2", (yyvsp[(1) - (1)].lex).line); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setAggregate(2, true); + ;} + break; + + case 130: + + { + FRAG_VERT_ONLY("mat3", (yyvsp[(1) - (1)].lex).line); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setAggregate(3, true); + ;} + break; + + case 131: + + { + FRAG_VERT_ONLY("mat4", (yyvsp[(1) - (1)].lex).line); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).setAggregate(4, true); + ;} + break; + + case 132: + + { + FRAG_VERT_ONLY("sampler2D", (yyvsp[(1) - (1)].lex).line); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtSampler2D, qual, (yyvsp[(1) - (1)].lex).line); + ;} + break; + + case 133: + + { + FRAG_VERT_ONLY("samplerCube", (yyvsp[(1) - (1)].lex).line); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtSamplerCube, qual, (yyvsp[(1) - (1)].lex).line); + ;} + break; + + case 134: + + { + FRAG_VERT_ONLY("struct", (yyvsp[(1) - (1)].interm.type).line); + (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type); + (yyval.interm.type).qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + ;} + break; + + case 135: + + { + // + // This is for user defined type names. The lexical phase looked up the + // type. + // + TType& structure = static_cast<TVariable*>((yyvsp[(1) - (1)].lex).symbol)->getType(); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtStruct, qual, (yyvsp[(1) - (1)].lex).line); + (yyval.interm.type).userDef = &structure; + ;} + break; + + case 136: + + { + if (context->reservedErrorCheck((yyvsp[(2) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string)) + context->recover(); + + TType* structure = new TType((yyvsp[(4) - (5)].interm.typeList), *(yyvsp[(2) - (5)].lex).string); + TVariable* userTypeDef = new TVariable((yyvsp[(2) - (5)].lex).string, *structure, true); + if (! context->symbolTable.insert(*userTypeDef)) { + context->error((yyvsp[(2) - (5)].lex).line, "redefinition", (yyvsp[(2) - (5)].lex).string->c_str(), "struct"); + context->recover(); + } + (yyval.interm.type).setBasic(EbtStruct, EvqTemporary, (yyvsp[(1) - (5)].lex).line); + (yyval.interm.type).userDef = structure; + ;} + break; + + case 137: + + { + TType* structure = new TType((yyvsp[(3) - (4)].interm.typeList), TString("")); + (yyval.interm.type).setBasic(EbtStruct, EvqTemporary, (yyvsp[(1) - (4)].lex).line); + (yyval.interm.type).userDef = structure; + ;} + break; + + case 138: + + { + (yyval.interm.typeList) = (yyvsp[(1) - (1)].interm.typeList); + ;} + break; + + case 139: + + { + (yyval.interm.typeList) = (yyvsp[(1) - (2)].interm.typeList); + for (unsigned int i = 0; i < (yyvsp[(2) - (2)].interm.typeList)->size(); ++i) { + for (unsigned int j = 0; j < (yyval.interm.typeList)->size(); ++j) { + if ((*(yyval.interm.typeList))[j].type->getFieldName() == (*(yyvsp[(2) - (2)].interm.typeList))[i].type->getFieldName()) { + context->error((*(yyvsp[(2) - (2)].interm.typeList))[i].line, "duplicate field name in structure:", "struct", (*(yyvsp[(2) - (2)].interm.typeList))[i].type->getFieldName().c_str()); + context->recover(); + } + } + (yyval.interm.typeList)->push_back((*(yyvsp[(2) - (2)].interm.typeList))[i]); + } + ;} + break; + + case 140: + + { + (yyval.interm.typeList) = (yyvsp[(2) - (3)].interm.typeList); + + if (context->voidErrorCheck((yyvsp[(1) - (3)].interm.type).line, (*(yyvsp[(2) - (3)].interm.typeList))[0].type->getFieldName(), (yyvsp[(1) - (3)].interm.type))) { + context->recover(); + } + for (unsigned int i = 0; i < (yyval.interm.typeList)->size(); ++i) { + // + // Careful not to replace already known aspects of type, like array-ness + // + TType* type = (*(yyval.interm.typeList))[i].type; + type->setBasicType((yyvsp[(1) - (3)].interm.type).type); + type->setNominalSize((yyvsp[(1) - (3)].interm.type).size); + type->setMatrix((yyvsp[(1) - (3)].interm.type).matrix); + type->setPrecision((yyvsp[(1) - (3)].interm.type).precision); + + // don't allow arrays of arrays + if (type->isArray()) { + if (context->arrayTypeErrorCheck((yyvsp[(1) - (3)].interm.type).line, (yyvsp[(1) - (3)].interm.type))) + context->recover(); + } + if ((yyvsp[(1) - (3)].interm.type).array) + type->setArraySize((yyvsp[(1) - (3)].interm.type).arraySize); + if ((yyvsp[(1) - (3)].interm.type).userDef) { + type->setStruct((yyvsp[(1) - (3)].interm.type).userDef->getStruct()); + type->setTypeName((yyvsp[(1) - (3)].interm.type).userDef->getTypeName()); + } + } + ;} + break; + + case 141: + + { + (yyval.interm.typeList) = NewPoolTTypeList(); + (yyval.interm.typeList)->push_back((yyvsp[(1) - (1)].interm.typeLine)); + ;} + break; + + case 142: + + { + (yyval.interm.typeList)->push_back((yyvsp[(3) - (3)].interm.typeLine)); + ;} + break; + + case 143: + + { + if (context->reservedErrorCheck((yyvsp[(1) - (1)].lex).line, *(yyvsp[(1) - (1)].lex).string)) + context->recover(); + + (yyval.interm.typeLine).type = new TType(EbtVoid, EbpUndefined); + (yyval.interm.typeLine).line = (yyvsp[(1) - (1)].lex).line; + (yyval.interm.typeLine).type->setFieldName(*(yyvsp[(1) - (1)].lex).string); + ;} + break; + + case 144: + + { + if (context->reservedErrorCheck((yyvsp[(1) - (4)].lex).line, *(yyvsp[(1) - (4)].lex).string)) + context->recover(); + + (yyval.interm.typeLine).type = new TType(EbtVoid, EbpUndefined); + (yyval.interm.typeLine).line = (yyvsp[(1) - (4)].lex).line; + (yyval.interm.typeLine).type->setFieldName(*(yyvsp[(1) - (4)].lex).string); + + int size; + if (context->arraySizeErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(3) - (4)].interm.intermTypedNode), size)) + context->recover(); + (yyval.interm.typeLine).type->setArraySize(size); + ;} + break; + + case 145: + + { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;} + break; + + case 146: + + { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;} + break; + + case 147: + + { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermAggregate); ;} + break; + + case 148: + + { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;} + break; + + case 149: + + { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;} + break; + + case 150: + + { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;} + break; + + case 151: + + { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;} + break; + + case 152: + + { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;} + break; + + case 153: + + { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;} + break; + + case 154: + + { (yyval.interm.intermAggregate) = 0; ;} + break; + + case 155: + + { context->symbolTable.push(); ;} + break; + + case 156: + + { context->symbolTable.pop(); ;} + break; + + case 157: + + { + if ((yyvsp[(3) - (5)].interm.intermAggregate) != 0) { + (yyvsp[(3) - (5)].interm.intermAggregate)->setOp(EOpSequence); + (yyvsp[(3) - (5)].interm.intermAggregate)->setEndLine((yyvsp[(5) - (5)].lex).line); + } + (yyval.interm.intermAggregate) = (yyvsp[(3) - (5)].interm.intermAggregate); + ;} + break; + + case 158: + + { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;} + break; + + case 159: + + { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;} + break; + + case 160: + + { + (yyval.interm.intermNode) = 0; + ;} + break; + + case 161: + + { + if ((yyvsp[(2) - (3)].interm.intermAggregate)) { + (yyvsp[(2) - (3)].interm.intermAggregate)->setOp(EOpSequence); + (yyvsp[(2) - (3)].interm.intermAggregate)->setEndLine((yyvsp[(3) - (3)].lex).line); + } + (yyval.interm.intermNode) = (yyvsp[(2) - (3)].interm.intermAggregate); + ;} + break; + + case 162: + + { + (yyval.interm.intermAggregate) = context->intermediate.makeAggregate((yyvsp[(1) - (1)].interm.intermNode), 0); + ;} + break; + + case 163: + + { + (yyval.interm.intermAggregate) = context->intermediate.growAggregate((yyvsp[(1) - (2)].interm.intermAggregate), (yyvsp[(2) - (2)].interm.intermNode), 0); + ;} + break; + + case 164: + + { (yyval.interm.intermNode) = 0; ;} + break; + + case 165: + + { (yyval.interm.intermNode) = static_cast<TIntermNode*>((yyvsp[(1) - (2)].interm.intermTypedNode)); ;} + break; + + case 166: + + { + if (context->boolErrorCheck((yyvsp[(1) - (5)].lex).line, (yyvsp[(3) - (5)].interm.intermTypedNode))) + context->recover(); + (yyval.interm.intermNode) = context->intermediate.addSelection((yyvsp[(3) - (5)].interm.intermTypedNode), (yyvsp[(5) - (5)].interm.nodePair), (yyvsp[(1) - (5)].lex).line); + ;} + break; + + case 167: + + { + (yyval.interm.nodePair).node1 = (yyvsp[(1) - (3)].interm.intermNode); + (yyval.interm.nodePair).node2 = (yyvsp[(3) - (3)].interm.intermNode); + ;} + break; + + case 168: + + { + (yyval.interm.nodePair).node1 = (yyvsp[(1) - (1)].interm.intermNode); + (yyval.interm.nodePair).node2 = 0; + ;} + break; + + case 169: + + { + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); + if (context->boolErrorCheck((yyvsp[(1) - (1)].interm.intermTypedNode)->getLine(), (yyvsp[(1) - (1)].interm.intermTypedNode))) + context->recover(); + ;} + break; + + case 170: + + { + TIntermNode* intermNode; + if (context->structQualifierErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type))) + context->recover(); + if (context->boolErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type))) + context->recover(); + + if (!context->executeInitializer((yyvsp[(2) - (4)].lex).line, *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), (yyvsp[(4) - (4)].interm.intermTypedNode), intermNode)) + (yyval.interm.intermTypedNode) = (yyvsp[(4) - (4)].interm.intermTypedNode); + else { + context->recover(); + (yyval.interm.intermTypedNode) = 0; + } + ;} + break; + + case 171: + + { context->symbolTable.push(); ++context->loopNestingLevel; ;} + break; + + case 172: + + { + context->symbolTable.pop(); + (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopWhile, 0, (yyvsp[(4) - (6)].interm.intermTypedNode), 0, (yyvsp[(6) - (6)].interm.intermNode), (yyvsp[(1) - (6)].lex).line); + --context->loopNestingLevel; + ;} + break; + + case 173: + + { ++context->loopNestingLevel; ;} + break; + + case 174: + + { + if (context->boolErrorCheck((yyvsp[(8) - (8)].lex).line, (yyvsp[(6) - (8)].interm.intermTypedNode))) + context->recover(); + + (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopDoWhile, 0, (yyvsp[(6) - (8)].interm.intermTypedNode), 0, (yyvsp[(3) - (8)].interm.intermNode), (yyvsp[(4) - (8)].lex).line); + --context->loopNestingLevel; + ;} + break; + + case 175: + + { context->symbolTable.push(); ++context->loopNestingLevel; ;} + break; + + case 176: + + { + context->symbolTable.pop(); + (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopFor, (yyvsp[(4) - (7)].interm.intermNode), reinterpret_cast<TIntermTyped*>((yyvsp[(5) - (7)].interm.nodePair).node1), reinterpret_cast<TIntermTyped*>((yyvsp[(5) - (7)].interm.nodePair).node2), (yyvsp[(7) - (7)].interm.intermNode), (yyvsp[(1) - (7)].lex).line); + --context->loopNestingLevel; + ;} + break; + + case 177: + + { + (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); + ;} + break; + + case 178: + + { + (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); + ;} + break; + + case 179: + + { + (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); + ;} + break; + + case 180: + + { + (yyval.interm.intermTypedNode) = 0; + ;} + break; + + case 181: + + { + (yyval.interm.nodePair).node1 = (yyvsp[(1) - (2)].interm.intermTypedNode); + (yyval.interm.nodePair).node2 = 0; + ;} + break; + + case 182: + + { + (yyval.interm.nodePair).node1 = (yyvsp[(1) - (3)].interm.intermTypedNode); + (yyval.interm.nodePair).node2 = (yyvsp[(3) - (3)].interm.intermTypedNode); + ;} + break; + + case 183: + + { + if (context->loopNestingLevel <= 0) { + context->error((yyvsp[(1) - (2)].lex).line, "continue statement only allowed in loops", "", ""); + context->recover(); + } + (yyval.interm.intermNode) = context->intermediate.addBranch(EOpContinue, (yyvsp[(1) - (2)].lex).line); + ;} + break; + + case 184: + + { + if (context->loopNestingLevel <= 0) { + context->error((yyvsp[(1) - (2)].lex).line, "break statement only allowed in loops", "", ""); + context->recover(); + } + (yyval.interm.intermNode) = context->intermediate.addBranch(EOpBreak, (yyvsp[(1) - (2)].lex).line); + ;} + break; + + case 185: + + { + (yyval.interm.intermNode) = context->intermediate.addBranch(EOpReturn, (yyvsp[(1) - (2)].lex).line); + if (context->currentFunctionType->getBasicType() != EbtVoid) { + context->error((yyvsp[(1) - (2)].lex).line, "non-void function must return a value", "return", ""); + context->recover(); + } + ;} + break; + + case 186: + + { + (yyval.interm.intermNode) = context->intermediate.addBranch(EOpReturn, (yyvsp[(2) - (3)].interm.intermTypedNode), (yyvsp[(1) - (3)].lex).line); + context->functionReturnsValue = true; + if (context->currentFunctionType->getBasicType() == EbtVoid) { + context->error((yyvsp[(1) - (3)].lex).line, "void function cannot return a value", "return", ""); + context->recover(); + } else if (*(context->currentFunctionType) != (yyvsp[(2) - (3)].interm.intermTypedNode)->getType()) { + context->error((yyvsp[(1) - (3)].lex).line, "function return is not matching type:", "return", ""); + context->recover(); + } + ;} + break; + + case 187: + + { + FRAG_ONLY("discard", (yyvsp[(1) - (2)].lex).line); + (yyval.interm.intermNode) = context->intermediate.addBranch(EOpKill, (yyvsp[(1) - (2)].lex).line); + ;} + break; + + case 188: + + { + (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); + context->treeRoot = (yyval.interm.intermNode); + ;} + break; + + case 189: + + { + (yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[(1) - (2)].interm.intermNode), (yyvsp[(2) - (2)].interm.intermNode), 0); + context->treeRoot = (yyval.interm.intermNode); + ;} + break; + + case 190: + + { + (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); + ;} + break; + + case 191: + + { + (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); + ;} + break; + + case 192: + + { + TFunction* function = (yyvsp[(1) - (1)].interm).function; + TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName())); + // + // Note: 'prevDec' could be 'function' if this is the first time we've seen function + // as it would have just been put in the symbol table. Otherwise, we're looking up + // an earlier occurance. + // + if (prevDec->isDefined()) { + // + // Then this function already has a body. + // + context->error((yyvsp[(1) - (1)].interm).line, "function already has a body", function->getName().c_str(), ""); + context->recover(); + } + prevDec->setDefined(); + + // + // Raise error message if main function takes any parameters or return anything other than void + // + if (function->getName() == "main") { + if (function->getParamCount() > 0) { + context->error((yyvsp[(1) - (1)].interm).line, "function cannot take any parameter(s)", function->getName().c_str(), ""); + context->recover(); + } + if (function->getReturnType().getBasicType() != EbtVoid) { + context->error((yyvsp[(1) - (1)].interm).line, "", function->getReturnType().getBasicString(), "main function cannot return a value"); + context->recover(); + } + } + + // + // New symbol table scope for body of function plus its arguments + // + context->symbolTable.push(); + + // + // Remember the return type for later checking for RETURN statements. + // + context->currentFunctionType = &(prevDec->getReturnType()); + context->functionReturnsValue = false; + + // + // Insert parameters into the symbol table. + // If the parameter has no name, it's not an error, just don't insert it + // (could be used for unused args). + // + // Also, accumulate the list of parameters into the HIL, so lower level code + // knows where to find parameters. + // + TIntermAggregate* paramNodes = new TIntermAggregate; + for (int i = 0; i < function->getParamCount(); i++) { + const TParameter& param = function->getParam(i); + if (param.name != 0) { + TVariable *variable = new TVariable(param.name, *param.type); + // + // Insert the parameters with name in the symbol table. + // + if (! context->symbolTable.insert(*variable)) { + context->error((yyvsp[(1) - (1)].interm).line, "redefinition", variable->getName().c_str(), ""); + context->recover(); + delete variable; + } + + // + // Add the parameter to the HIL + // + paramNodes = context->intermediate.growAggregate( + paramNodes, + context->intermediate.addSymbol(variable->getUniqueId(), + variable->getName(), + variable->getType(), (yyvsp[(1) - (1)].interm).line), + (yyvsp[(1) - (1)].interm).line); + } else { + paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, (yyvsp[(1) - (1)].interm).line), (yyvsp[(1) - (1)].interm).line); + } + } + context->intermediate.setAggregateOperator(paramNodes, EOpParameters, (yyvsp[(1) - (1)].interm).line); + (yyvsp[(1) - (1)].interm).intermAggregate = paramNodes; + context->loopNestingLevel = 0; + ;} + break; + + case 193: + + { + //?? Check that all paths return a value if return type != void ? + // May be best done as post process phase on intermediate code + if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) { + context->error((yyvsp[(1) - (3)].interm).line, "function does not return a value:", "", (yyvsp[(1) - (3)].interm).function->getName().c_str()); + context->recover(); + } + context->symbolTable.pop(); + (yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermAggregate, (yyvsp[(3) - (3)].interm.intermNode), 0); + context->intermediate.setAggregateOperator((yyval.interm.intermNode), EOpFunction, (yyvsp[(1) - (3)].interm).line); + (yyval.interm.intermNode)->getAsAggregate()->setName((yyvsp[(1) - (3)].interm).function->getMangledName().c_str()); + (yyval.interm.intermNode)->getAsAggregate()->setType((yyvsp[(1) - (3)].interm).function->getReturnType()); + + // store the pragma information for debug and optimize and other vendor specific + // information. This information can be queried from the parse tree + (yyval.interm.intermNode)->getAsAggregate()->setOptimize(context->contextPragma.optimize); + (yyval.interm.intermNode)->getAsAggregate()->setDebug(context->contextPragma.debug); + (yyval.interm.intermNode)->getAsAggregate()->addToPragmaTable(context->contextPragma.pragmaTable); + + if ((yyvsp[(3) - (3)].interm.intermNode) && (yyvsp[(3) - (3)].interm.intermNode)->getAsAggregate()) + (yyval.interm.intermNode)->getAsAggregate()->setEndLine((yyvsp[(3) - (3)].interm.intermNode)->getAsAggregate()->getEndLine()); + ;} + break; + + +/* Line 1267 of yacc.c. */ + + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (context, YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (context, yymsg); + } + else + { + yyerror (context, YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval, context); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse look-ahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp, context); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (context, YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, context); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp, context); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + + + + +int glslang_parse(TParseContext* context) { + return yyparse(context); +} + + diff --git a/Source/ThirdParty/ANGLE/src/compiler/glslang_tab.h b/Source/ThirdParty/ANGLE/src/compiler/glslang_tab.h new file mode 100644 index 000000000..fa8480d3a --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/glslang_tab.h @@ -0,0 +1,274 @@ +/* A Bison parser, made by GNU Bison 2.3. */ + +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + INVARIANT = 258, + HIGH_PRECISION = 259, + MEDIUM_PRECISION = 260, + LOW_PRECISION = 261, + PRECISION = 262, + ATTRIBUTE = 263, + CONST_QUAL = 264, + BOOL_TYPE = 265, + FLOAT_TYPE = 266, + INT_TYPE = 267, + BREAK = 268, + CONTINUE = 269, + DO = 270, + ELSE = 271, + FOR = 272, + IF = 273, + DISCARD = 274, + RETURN = 275, + BVEC2 = 276, + BVEC3 = 277, + BVEC4 = 278, + IVEC2 = 279, + IVEC3 = 280, + IVEC4 = 281, + VEC2 = 282, + VEC3 = 283, + VEC4 = 284, + MATRIX2 = 285, + MATRIX3 = 286, + MATRIX4 = 287, + IN_QUAL = 288, + OUT_QUAL = 289, + INOUT_QUAL = 290, + UNIFORM = 291, + VARYING = 292, + STRUCT = 293, + VOID_TYPE = 294, + WHILE = 295, + SAMPLER2D = 296, + SAMPLERCUBE = 297, + IDENTIFIER = 298, + TYPE_NAME = 299, + FLOATCONSTANT = 300, + INTCONSTANT = 301, + BOOLCONSTANT = 302, + FIELD_SELECTION = 303, + LEFT_OP = 304, + RIGHT_OP = 305, + INC_OP = 306, + DEC_OP = 307, + LE_OP = 308, + GE_OP = 309, + EQ_OP = 310, + NE_OP = 311, + AND_OP = 312, + OR_OP = 313, + XOR_OP = 314, + MUL_ASSIGN = 315, + DIV_ASSIGN = 316, + ADD_ASSIGN = 317, + MOD_ASSIGN = 318, + LEFT_ASSIGN = 319, + RIGHT_ASSIGN = 320, + AND_ASSIGN = 321, + XOR_ASSIGN = 322, + OR_ASSIGN = 323, + SUB_ASSIGN = 324, + LEFT_PAREN = 325, + RIGHT_PAREN = 326, + LEFT_BRACKET = 327, + RIGHT_BRACKET = 328, + LEFT_BRACE = 329, + RIGHT_BRACE = 330, + DOT = 331, + COMMA = 332, + COLON = 333, + EQUAL = 334, + SEMICOLON = 335, + BANG = 336, + DASH = 337, + TILDE = 338, + PLUS = 339, + STAR = 340, + SLASH = 341, + PERCENT = 342, + LEFT_ANGLE = 343, + RIGHT_ANGLE = 344, + VERTICAL_BAR = 345, + CARET = 346, + AMPERSAND = 347, + QUESTION = 348 + }; +#endif +/* Tokens. */ +#define INVARIANT 258 +#define HIGH_PRECISION 259 +#define MEDIUM_PRECISION 260 +#define LOW_PRECISION 261 +#define PRECISION 262 +#define ATTRIBUTE 263 +#define CONST_QUAL 264 +#define BOOL_TYPE 265 +#define FLOAT_TYPE 266 +#define INT_TYPE 267 +#define BREAK 268 +#define CONTINUE 269 +#define DO 270 +#define ELSE 271 +#define FOR 272 +#define IF 273 +#define DISCARD 274 +#define RETURN 275 +#define BVEC2 276 +#define BVEC3 277 +#define BVEC4 278 +#define IVEC2 279 +#define IVEC3 280 +#define IVEC4 281 +#define VEC2 282 +#define VEC3 283 +#define VEC4 284 +#define MATRIX2 285 +#define MATRIX3 286 +#define MATRIX4 287 +#define IN_QUAL 288 +#define OUT_QUAL 289 +#define INOUT_QUAL 290 +#define UNIFORM 291 +#define VARYING 292 +#define STRUCT 293 +#define VOID_TYPE 294 +#define WHILE 295 +#define SAMPLER2D 296 +#define SAMPLERCUBE 297 +#define IDENTIFIER 298 +#define TYPE_NAME 299 +#define FLOATCONSTANT 300 +#define INTCONSTANT 301 +#define BOOLCONSTANT 302 +#define FIELD_SELECTION 303 +#define LEFT_OP 304 +#define RIGHT_OP 305 +#define INC_OP 306 +#define DEC_OP 307 +#define LE_OP 308 +#define GE_OP 309 +#define EQ_OP 310 +#define NE_OP 311 +#define AND_OP 312 +#define OR_OP 313 +#define XOR_OP 314 +#define MUL_ASSIGN 315 +#define DIV_ASSIGN 316 +#define ADD_ASSIGN 317 +#define MOD_ASSIGN 318 +#define LEFT_ASSIGN 319 +#define RIGHT_ASSIGN 320 +#define AND_ASSIGN 321 +#define XOR_ASSIGN 322 +#define OR_ASSIGN 323 +#define SUB_ASSIGN 324 +#define LEFT_PAREN 325 +#define RIGHT_PAREN 326 +#define LEFT_BRACKET 327 +#define RIGHT_BRACKET 328 +#define LEFT_BRACE 329 +#define RIGHT_BRACE 330 +#define DOT 331 +#define COMMA 332 +#define COLON 333 +#define EQUAL 334 +#define SEMICOLON 335 +#define BANG 336 +#define DASH 337 +#define TILDE 338 +#define PLUS 339 +#define STAR 340 +#define SLASH 341 +#define PERCENT 342 +#define LEFT_ANGLE 343 +#define RIGHT_ANGLE 344 +#define VERTICAL_BAR 345 +#define CARET 346 +#define AMPERSAND 347 +#define QUESTION 348 + + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE + +{ + struct { + TSourceLoc line; + union { + TString *string; + float f; + int i; + bool b; + }; + TSymbol* symbol; + } lex; + struct { + TSourceLoc line; + TOperator op; + union { + TIntermNode* intermNode; + TIntermNodePair nodePair; + TIntermTyped* intermTypedNode; + TIntermAggregate* intermAggregate; + }; + union { + TPublicType type; + TPrecision precision; + TQualifier qualifier; + TFunction* function; + TParameter param; + TTypeLine typeLine; + TTypeList* typeList; + }; + } interm; +} +/* Line 1529 of yacc.c. */ + + YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + diff --git a/Source/ThirdParty/ANGLE/src/compiler/intermOut.cpp b/Source/ThirdParty/ANGLE/src/compiler/intermOut.cpp new file mode 100644 index 000000000..798a69af7 --- /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(TInfoSinkBase& i) : sink(i) { } + TInfoSinkBase& sink; + +protected: + void visitSymbol(TIntermSymbol*); + void visitConstantUnion(TIntermConstantUnion*); + bool visitBinary(Visit visit, TIntermBinary*); + bool visitUnary(Visit visit, TIntermUnary*); + bool visitSelection(Visit visit, TIntermSelection*); + bool visitAggregate(Visit visit, TIntermAggregate*); + bool visitLoop(Visit visit, TIntermLoop*); + bool visitBranch(Visit visit, TIntermBranch*); +}; + +TString TType::getCompleteString() const +{ + TStringStream stream; + + if (qualifier != EvqTemporary && qualifier != EvqGlobal) + stream << getQualifierString() << " " << getPrecisionString() << " "; + if (array) + stream << "array of "; + if (matrix) + stream << size << "X" << size << " matrix of "; + else if (size > 1) + stream << size << "-component vector of "; + + stream << getBasicString(); + return stream.str(); +} + +// +// Helper functions for printing, not part of traversing. +// + +void OutputTreeText(TInfoSinkBase& sink, TIntermNode* node, const int depth) +{ + int i; + + sink.location(node->getLine()); + + for (i = 0; i < depth; ++i) + sink << " "; +} + +// +// The rest of the file are the traversal functions. The last one +// is the one that starts the traversal. +// +// Return true from interior nodes to have the external traversal +// continue on to children. If you process children yourself, +// return false. +// + +void TOutputTraverser::visitSymbol(TIntermSymbol* node) +{ + OutputTreeText(sink, node, depth); + + sink << "'" << node->getSymbol() << "' "; + sink << "(" << node->getCompleteString() << ")\n"; +} + +bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node) +{ + TInfoSinkBase& out = sink; + + OutputTreeText(out, node, depth); + + switch (node->getOp()) { + case EOpAssign: out << "move second child to first child"; break; + case EOpInitialize: out << "initialize first child with second child"; break; + case EOpAddAssign: out << "add second child into first child"; break; + case EOpSubAssign: out << "subtract second child into first child"; break; + case EOpMulAssign: out << "multiply second child into first child"; break; + case EOpVectorTimesMatrixAssign: out << "matrix mult second child into first child"; break; + case EOpVectorTimesScalarAssign: out << "vector scale second child into first child"; break; + case EOpMatrixTimesScalarAssign: out << "matrix scale second child into first child"; break; + case EOpMatrixTimesMatrixAssign: out << "matrix mult second child into first child"; break; + case EOpDivAssign: out << "divide second child into first child"; break; + case EOpIndexDirect: out << "direct index"; break; + case EOpIndexIndirect: out << "indirect index"; break; + case EOpIndexDirectStruct: out << "direct index for structure"; break; + case EOpVectorSwizzle: out << "vector swizzle"; break; + + case EOpAdd: out << "add"; break; + case EOpSub: out << "subtract"; break; + case EOpMul: out << "component-wise multiply"; break; + case EOpDiv: out << "divide"; break; + case EOpEqual: out << "Compare Equal"; break; + case EOpNotEqual: out << "Compare Not Equal"; break; + case EOpLessThan: out << "Compare Less Than"; break; + case EOpGreaterThan: out << "Compare Greater Than"; break; + case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; + case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; + + case EOpVectorTimesScalar: out << "vector-scale"; break; + case EOpVectorTimesMatrix: out << "vector-times-matrix"; break; + case EOpMatrixTimesVector: out << "matrix-times-vector"; break; + case EOpMatrixTimesScalar: out << "matrix-scale"; break; + case EOpMatrixTimesMatrix: out << "matrix-multiply"; break; + + case EOpLogicalOr: out << "logical-or"; break; + case EOpLogicalXor: out << "logical-xor"; break; + case EOpLogicalAnd: out << "logical-and"; break; + default: out << "<unknown op>"; + } + + out << " (" << node->getCompleteString() << ")"; + + out << "\n"; + + return true; +} + +bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node) +{ + TInfoSinkBase& out = sink; + + OutputTreeText(out, node, depth); + + switch (node->getOp()) { + case EOpNegative: out << "Negate value"; break; + case EOpVectorLogicalNot: + case EOpLogicalNot: out << "Negate conditional"; break; + + case EOpPostIncrement: out << "Post-Increment"; break; + case EOpPostDecrement: out << "Post-Decrement"; break; + case EOpPreIncrement: out << "Pre-Increment"; break; + case EOpPreDecrement: out << "Pre-Decrement"; break; + + case EOpConvIntToBool: out << "Convert int to bool"; break; + case EOpConvFloatToBool:out << "Convert float to bool";break; + case EOpConvBoolToFloat:out << "Convert bool to float";break; + case EOpConvIntToFloat: out << "Convert int to float"; break; + case EOpConvFloatToInt: out << "Convert float to int"; break; + case EOpConvBoolToInt: out << "Convert bool to int"; break; + + case EOpRadians: out << "radians"; break; + case EOpDegrees: out << "degrees"; break; + case EOpSin: out << "sine"; break; + case EOpCos: out << "cosine"; break; + case EOpTan: out << "tangent"; break; + case EOpAsin: out << "arc sine"; break; + case EOpAcos: out << "arc cosine"; break; + case EOpAtan: out << "arc tangent"; break; + + case EOpExp: out << "exp"; break; + case EOpLog: out << "log"; break; + case EOpExp2: out << "exp2"; break; + case EOpLog2: out << "log2"; break; + case EOpSqrt: out << "sqrt"; break; + case EOpInverseSqrt: out << "inverse sqrt"; break; + + case EOpAbs: out << "Absolute value"; break; + case EOpSign: out << "Sign"; break; + case EOpFloor: out << "Floor"; break; + case EOpCeil: out << "Ceiling"; break; + case EOpFract: out << "Fraction"; break; + + case EOpLength: out << "length"; break; + case EOpNormalize: out << "normalize"; break; + // case EOpDPdx: out << "dPdx"; break; + // case EOpDPdy: out << "dPdy"; break; + // case EOpFwidth: out << "fwidth"; break; + + case EOpAny: out << "any"; break; + case EOpAll: out << "all"; break; + + default: out.message(EPrefixError, "Bad unary op"); + } + + out << " (" << node->getCompleteString() << ")"; + + out << "\n"; + + return true; +} + +bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node) +{ + TInfoSinkBase& out = sink; + + if (node->getOp() == EOpNull) { + out.message(EPrefixError, "node is still EOpNull!"); + return true; + } + + OutputTreeText(out, node, depth); + + switch (node->getOp()) { + case EOpSequence: out << "Sequence\n"; return true; + case EOpComma: out << "Comma\n"; return true; + case EOpFunction: out << "Function Definition: " << node->getName(); break; + case EOpFunctionCall: out << "Function Call: " << node->getName(); break; + case EOpParameters: out << "Function Parameters: "; break; + + case EOpConstructFloat: out << "Construct float"; break; + case EOpConstructVec2: out << "Construct vec2"; break; + case EOpConstructVec3: out << "Construct vec3"; break; + case EOpConstructVec4: out << "Construct vec4"; break; + case EOpConstructBool: out << "Construct bool"; break; + case EOpConstructBVec2: out << "Construct bvec2"; break; + case EOpConstructBVec3: out << "Construct bvec3"; break; + case EOpConstructBVec4: out << "Construct bvec4"; break; + case EOpConstructInt: out << "Construct int"; break; + case EOpConstructIVec2: out << "Construct ivec2"; break; + case EOpConstructIVec3: out << "Construct ivec3"; break; + case EOpConstructIVec4: out << "Construct ivec4"; break; + case EOpConstructMat2: out << "Construct mat2"; break; + case EOpConstructMat3: out << "Construct mat3"; break; + case EOpConstructMat4: out << "Construct mat4"; break; + case EOpConstructStruct: out << "Construct structure"; break; + + case EOpLessThan: out << "Compare Less Than"; break; + case EOpGreaterThan: out << "Compare Greater Than"; break; + case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; + case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; + case EOpVectorEqual: out << "Equal"; break; + case EOpVectorNotEqual: out << "NotEqual"; break; + + case EOpMod: out << "mod"; break; + case EOpPow: out << "pow"; break; + + case EOpAtan: out << "arc tangent"; break; + + case EOpMin: out << "min"; break; + case EOpMax: out << "max"; break; + case EOpClamp: out << "clamp"; break; + case EOpMix: out << "mix"; break; + case EOpStep: out << "step"; break; + case EOpSmoothStep: out << "smoothstep"; break; + + case EOpDistance: out << "distance"; break; + case EOpDot: out << "dot-product"; break; + case EOpCross: out << "cross-product"; break; + case EOpFaceForward: out << "face-forward"; break; + case EOpReflect: out << "reflect"; break; + case EOpRefract: out << "refract"; break; + case EOpMul: out << "component-wise multiply"; break; + + default: out.message(EPrefixError, "Bad aggregation op"); + } + + if (node->getOp() != EOpSequence && node->getOp() != EOpParameters) + out << " (" << node->getCompleteString() << ")"; + + out << "\n"; + + return true; +} + +bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node) +{ + TInfoSinkBase& out = sink; + + OutputTreeText(out, node, depth); + + out << "Test condition and select"; + out << " (" << node->getCompleteString() << ")\n"; + + ++depth; + + OutputTreeText(sink, node, depth); + out << "Condition\n"; + node->getCondition()->traverse(this); + + OutputTreeText(sink, node, depth); + if (node->getTrueBlock()) { + out << "true case\n"; + node->getTrueBlock()->traverse(this); + } else + out << "true case is null\n"; + + if (node->getFalseBlock()) { + OutputTreeText(sink, node, depth); + out << "false case\n"; + node->getFalseBlock()->traverse(this); + } + + --depth; + + return false; +} + +void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) +{ + TInfoSinkBase& out = sink; + + int size = node->getType().getObjectSize(); + + for (int i = 0; i < size; i++) { + OutputTreeText(out, node, depth); + switch (node->getUnionArrayPointer()[i].getType()) { + case EbtBool: + if (node->getUnionArrayPointer()[i].getBConst()) + out << "true"; + else + out << "false"; + + out << " (" << "const bool" << ")"; + out << "\n"; + break; + case EbtFloat: + out << node->getUnionArrayPointer()[i].getFConst(); + out << " (const float)\n"; + break; + case EbtInt: + out << node->getUnionArrayPointer()[i].getIConst(); + out << " (const int)\n"; + break; + default: + out.message(EPrefixInternalError, "Unknown constant", node->getLine()); + break; + } + } +} + +bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node) +{ + TInfoSinkBase& out = sink; + + OutputTreeText(out, node, depth); + + out << "Loop with condition "; + if (node->getType() == ELoopDoWhile) + out << "not "; + out << "tested first\n"; + + ++depth; + + OutputTreeText(sink, node, depth); + if (node->getCondition()) { + out << "Loop Condition\n"; + node->getCondition()->traverse(this); + } else + out << "No loop condition\n"; + + OutputTreeText(sink, node, depth); + if (node->getBody()) { + out << "Loop Body\n"; + node->getBody()->traverse(this); + } else + out << "No loop body\n"; + + if (node->getExpression()) { + OutputTreeText(sink, node, depth); + out << "Loop Terminal Expression\n"; + node->getExpression()->traverse(this); + } + + --depth; + + return false; +} + +bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node) +{ + TInfoSinkBase& out = sink; + + OutputTreeText(out, node, depth); + + switch (node->getFlowOp()) { + case EOpKill: out << "Branch: Kill"; break; + case EOpBreak: out << "Branch: Break"; break; + case EOpContinue: out << "Branch: Continue"; break; + case EOpReturn: out << "Branch: Return"; break; + default: out << "Branch: Unknown Branch"; break; + } + + if (node->getExpression()) { + out << " with expression\n"; + ++depth; + node->getExpression()->traverse(this); + --depth; + } else + out << "\n"; + + return false; +} + +// +// This function is the one to call externally to start the traversal. +// Individual functions can be initialized to 0 to skip processing of that +// type of node. It's children will still be processed. +// +void TIntermediate::outputTree(TIntermNode* root) +{ + if (root == 0) + return; + + TOutputTraverser it(infoSink.info); + + root->traverse(&it); +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/intermediate.h b/Source/ThirdParty/ANGLE/src/compiler/intermediate.h new file mode 100644 index 000000000..a8af5ab06 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/intermediate.h @@ -0,0 +1,544 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// +// Definition of the in-memory high-level intermediate representation +// of shaders. This is a tree that parser creates. +// +// Nodes in the tree are defined as a hierarchy of classes derived from +// TIntermNode. Each is a node in a tree. There is no preset branching factor; +// each node can have it's own type of list of children. +// + +#ifndef __INTERMEDIATE_H +#define __INTERMEDIATE_H + +#include "compiler/Common.h" +#include "compiler/Types.h" +#include "compiler/ConstantUnion.h" + +// +// Operators used by the high-level (parse tree) representation. +// +enum TOperator { + EOpNull, // if in a node, should only mean a node is still being built + EOpSequence, // denotes a list of statements, or parameters, etc. + EOpFunctionCall, + EOpFunction, // For function definition + EOpParameters, // an aggregate listing the parameters to a function + + EOpDeclaration, + EOpPrototype, + + // + // Unary operators + // + + EOpNegative, + EOpLogicalNot, + EOpVectorLogicalNot, + + EOpPostIncrement, + EOpPostDecrement, + EOpPreIncrement, + EOpPreDecrement, + + EOpConvIntToBool, + EOpConvFloatToBool, + EOpConvBoolToFloat, + EOpConvIntToFloat, + EOpConvFloatToInt, + EOpConvBoolToInt, + + // + // binary operations + // + + EOpAdd, + EOpSub, + EOpMul, + EOpDiv, + EOpEqual, + EOpNotEqual, + EOpVectorEqual, + EOpVectorNotEqual, + EOpLessThan, + EOpGreaterThan, + EOpLessThanEqual, + EOpGreaterThanEqual, + EOpComma, + + EOpVectorTimesScalar, + EOpVectorTimesMatrix, + EOpMatrixTimesVector, + EOpMatrixTimesScalar, + + EOpLogicalOr, + EOpLogicalXor, + EOpLogicalAnd, + + EOpIndexDirect, + EOpIndexIndirect, + EOpIndexDirectStruct, + + EOpVectorSwizzle, + + // + // Built-in functions potentially mapped to operators + // + + EOpRadians, + EOpDegrees, + EOpSin, + EOpCos, + EOpTan, + EOpAsin, + EOpAcos, + EOpAtan, + + EOpPow, + EOpExp, + EOpLog, + EOpExp2, + EOpLog2, + EOpSqrt, + EOpInverseSqrt, + + EOpAbs, + EOpSign, + EOpFloor, + EOpCeil, + EOpFract, + EOpMod, + EOpMin, + EOpMax, + EOpClamp, + EOpMix, + EOpStep, + EOpSmoothStep, + + EOpLength, + EOpDistance, + EOpDot, + EOpCross, + EOpNormalize, + EOpFaceForward, + EOpReflect, + EOpRefract, + + EOpDFdx, // Fragment only, OES_standard_derivatives extension + EOpDFdy, // Fragment only, OES_standard_derivatives extension + EOpFwidth, // Fragment only, OES_standard_derivatives extension + + EOpMatrixTimesMatrix, + + EOpAny, + EOpAll, + + // + // Branch + // + + EOpKill, // Fragment only + EOpReturn, + EOpBreak, + EOpContinue, + + // + // Constructors + // + + EOpConstructInt, + EOpConstructBool, + EOpConstructFloat, + EOpConstructVec2, + EOpConstructVec3, + EOpConstructVec4, + EOpConstructBVec2, + EOpConstructBVec3, + EOpConstructBVec4, + EOpConstructIVec2, + EOpConstructIVec3, + EOpConstructIVec4, + EOpConstructMat2, + EOpConstructMat3, + EOpConstructMat4, + EOpConstructStruct, + + // + // moves + // + + EOpAssign, + EOpInitialize, + EOpAddAssign, + EOpSubAssign, + EOpMulAssign, + EOpVectorTimesMatrixAssign, + EOpVectorTimesScalarAssign, + EOpMatrixTimesScalarAssign, + EOpMatrixTimesMatrixAssign, + EOpDivAssign, +}; + +extern const char* getOperatorString(TOperator op); + +class TIntermTraverser; +class TIntermAggregate; +class TIntermBinary; +class TIntermUnary; +class TIntermConstantUnion; +class TIntermSelection; +class TIntermTyped; +class TIntermSymbol; +class TIntermLoop; +class TInfoSink; + +// +// Base class for the tree nodes +// +class TIntermNode { +public: + POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + + TIntermNode() : line(0) {} + + TSourceLoc getLine() const { return line; } + void setLine(TSourceLoc l) { line = l; } + + virtual void traverse(TIntermTraverser*) = 0; + virtual TIntermTyped* getAsTyped() { return 0; } + virtual TIntermConstantUnion* getAsConstantUnion() { return 0; } + virtual TIntermAggregate* getAsAggregate() { return 0; } + virtual TIntermBinary* getAsBinaryNode() { return 0; } + virtual TIntermUnary* getAsUnaryNode() { return 0; } + virtual TIntermSelection* getAsSelectionNode() { return 0; } + virtual TIntermSymbol* getAsSymbolNode() { return 0; } + virtual TIntermLoop* getAsLoopNode() { return 0; } + virtual ~TIntermNode() { } + +protected: + TSourceLoc line; +}; + +// +// This is just to help yacc. +// +struct TIntermNodePair { + TIntermNode* node1; + TIntermNode* node2; +}; + +// +// Intermediate class for nodes that have a type. +// +class TIntermTyped : public TIntermNode { +public: + TIntermTyped(const TType& t) : type(t) { } + virtual TIntermTyped* getAsTyped() { return this; } + + void setType(const TType& t) { type = t; } + const TType& getType() const { return type; } + TType* getTypePointer() { return &type; } + + TBasicType getBasicType() const { return type.getBasicType(); } + TQualifier getQualifier() const { return type.getQualifier(); } + TPrecision getPrecision() const { return type.getPrecision(); } + int getNominalSize() const { return type.getNominalSize(); } + + bool isMatrix() const { return type.isMatrix(); } + bool isArray() const { return type.isArray(); } + bool isVector() const { return type.isVector(); } + bool isScalar() const { return type.isScalar(); } + const char* getBasicString() const { return type.getBasicString(); } + const char* getQualifierString() const { return type.getQualifierString(); } + TString getCompleteString() const { return type.getCompleteString(); } + +protected: + TType type; +}; + +// +// Handle for, do-while, and while loops. +// +enum TLoopType { + ELoopFor, + ELoopWhile, + ELoopDoWhile, +}; + +class TIntermLoop : public TIntermNode { +public: + TIntermLoop(TLoopType aType, + TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr, + TIntermNode* aBody) : + type(aType), + init(aInit), + cond(aCond), + expr(aExpr), + body(aBody), + unrollFlag(false) { } + + virtual TIntermLoop* getAsLoopNode() { return this; } + virtual void traverse(TIntermTraverser*); + + TLoopType getType() const { return type; } + TIntermNode* getInit() { return init; } + TIntermTyped* getCondition() { return cond; } + TIntermTyped* getExpression() { return expr; } + TIntermNode* getBody() { return body; } + + void setUnrollFlag(bool flag) { unrollFlag = flag; } + bool getUnrollFlag() { return unrollFlag; } + +protected: + TLoopType type; + TIntermNode* init; // for-loop initialization + TIntermTyped* cond; // loop exit condition + TIntermTyped* expr; // for-loop expression + TIntermNode* body; // loop body + + bool unrollFlag; // Whether the loop should be unrolled or not. +}; + +// +// Handle break, continue, return, and kill. +// +class TIntermBranch : public TIntermNode { +public: + TIntermBranch(TOperator op, TIntermTyped* e) : + flowOp(op), + expression(e) { } + + virtual void traverse(TIntermTraverser*); + + TOperator getFlowOp() { return flowOp; } + TIntermTyped* getExpression() { return expression; } + +protected: + TOperator flowOp; + TIntermTyped* expression; // non-zero except for "return exp;" statements +}; + +// +// Nodes that correspond to symbols or constants in the source code. +// +class TIntermSymbol : public TIntermTyped { +public: + // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from + // per process globalpoolallocator, then it causes increased memory usage per compile + // it is essential to use "symbol = sym" to assign to symbol + TIntermSymbol(int i, const TString& sym, const TType& t) : + TIntermTyped(t), id(i) { symbol = sym; originalSymbol = sym; } + + int getId() const { return id; } + const TString& getSymbol() const { return symbol; } + + void setId(int newId) { id = newId; } + void setSymbol(const TString& sym) { symbol = sym; } + + const TString& getOriginalSymbol() const { return originalSymbol; } + + virtual void traverse(TIntermTraverser*); + virtual TIntermSymbol* getAsSymbolNode() { return this; } + +protected: + int id; + TString symbol; + TString originalSymbol; +}; + +class TIntermConstantUnion : public TIntermTyped { +public: + TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { } + + ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; } + void setUnionArrayPointer(ConstantUnion *c) { unionArrayPointer = c; } + + virtual TIntermConstantUnion* getAsConstantUnion() { return this; } + virtual void traverse(TIntermTraverser*); + + TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&); + +protected: + ConstantUnion *unionArrayPointer; +}; + +// +// Intermediate class for node types that hold operators. +// +class TIntermOperator : public TIntermTyped { +public: + TOperator getOp() const { return op; } + void setOp(TOperator o) { op = o; } + + bool modifiesState() const; + bool isConstructor() const; + +protected: + TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {} + TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {} + TOperator op; +}; + +// +// Nodes for all the basic binary math operators. +// +class TIntermBinary : public TIntermOperator { +public: + TIntermBinary(TOperator o) : TIntermOperator(o) {} + + virtual TIntermBinary* getAsBinaryNode() { return this; } + virtual void traverse(TIntermTraverser*); + + void setLeft(TIntermTyped* n) { left = n; } + void setRight(TIntermTyped* n) { right = n; } + TIntermTyped* getLeft() const { return left; } + TIntermTyped* getRight() const { return right; } + bool promote(TInfoSink&); + +protected: + TIntermTyped* left; + TIntermTyped* right; +}; + +// +// Nodes for unary math operators. +// +class TIntermUnary : public TIntermOperator { +public: + TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {} + 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; +typedef TMap<TString, TString> TPragmaTable; +// +// Nodes that operate on an arbitrary sized set of children. +// +class TIntermAggregate : public TIntermOperator { +public: + TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0), endLine(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; } + + 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; } + void setEndLine(TSourceLoc line) { endLine = line; } + TSourceLoc getEndLine() const { return endLine; } + +protected: + TIntermAggregate(const TIntermAggregate&); // disallow copy constructor + TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator + TIntermSequence sequence; + TString name; + bool userDefined; // used for user defined function names + + bool optimize; + bool debug; + TPragmaTable *pragmaTable; + TSourceLoc endLine; +}; + +// +// For if tests. Simplified since there is no switch statement. +// +class TIntermSelection : public TIntermTyped { +public: + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : + TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {} + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : + TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {} + + 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 000000000..56890bd56 --- /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(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, TSourceLoc); + TIntermBranch* addBranch(TOperator, TSourceLoc); + TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc); + TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc); + bool postProcess(TIntermNode*); + void remove(TIntermNode*); + void outputTree(TIntermNode*); + +protected: + TInfoSink& infoSink; + +private: + void operator=(TIntermediate&); // prevent assignments +}; + +#endif // _LOCAL_INTERMEDIATE_INCLUDED_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/osinclude.h b/Source/ThirdParty/ANGLE/src/compiler/osinclude.h new file mode 100644 index 000000000..1af5064b0 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/osinclude.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. +// + +#ifndef __OSINCLUDE_H +#define __OSINCLUDE_H + +// +// This file contains contains os-specific datatypes and +// declares any os-specific functions. +// + +#if defined(_WIN32) || defined(_WIN64) +#define ANGLE_OS_WIN +#elif defined(__APPLE__) || defined(__linux__) || \ + defined(__FreeBSD__) || defined(__OpenBSD__) || \ + defined(__sun) +#define ANGLE_OS_POSIX +#else +#error Unsupported platform. +#endif + +#if defined(ANGLE_USE_NSPR) +#include "prthread.h" +#elif defined(ANGLE_OS_WIN) +#define STRICT +#define VC_EXTRALEAN 1 +#include <windows.h> +#elif defined(ANGLE_OS_POSIX) +#include <pthread.h> +#include <semaphore.h> +#include <errno.h> +#endif // ANGLE_USE_NSPR + + +#include "compiler/debug.h" + +// +// Thread Local Storage Operations +// +#if defined(ANGLE_USE_NSPR) +typedef PRUintn OS_TLSIndex; +#define OS_INVALID_TLS_INDEX 0xFFFFFFFF +#elif defined(ANGLE_OS_WIN) +typedef DWORD OS_TLSIndex; +#define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES) +#elif defined(ANGLE_OS_POSIX) +typedef unsigned int OS_TLSIndex; +#define OS_INVALID_TLS_INDEX 0xFFFFFFFF +#endif // ANGLE_USE_NSPR + +OS_TLSIndex OS_AllocTLSIndex(); +bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue); +bool OS_FreeTLSIndex(OS_TLSIndex nIndex); + +inline void* OS_GetTLSValue(OS_TLSIndex nIndex) +{ + ASSERT(nIndex != OS_INVALID_TLS_INDEX); +#if defined(ANGLE_USE_NSPR) + return PR_GetThreadPrivate(nIndex); +#elif defined(ANGLE_OS_WIN) + return TlsGetValue(nIndex); +#elif defined(ANGLE_OS_POSIX) + return pthread_getspecific(nIndex); +#endif // ANGLE_OS_WIN +} + +#endif // __OSINCLUDE_H diff --git a/Source/ThirdParty/ANGLE/src/compiler/ossource_nspr.cpp b/Source/ThirdParty/ANGLE/src/compiler/ossource_nspr.cpp new file mode 100644 index 000000000..f63d81e5d --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/ossource_nspr.cpp @@ -0,0 +1,43 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// +// This file contains the nspr specific functions +// +#include "compiler/osinclude.h" + +// +// Thread Local Storage Operations +// +OS_TLSIndex OS_AllocTLSIndex() +{ + PRUintn index; + PRStatus status = PR_NewThreadPrivateIndex(&index, NULL); + + if (status) { + assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage"); + return OS_INVALID_TLS_INDEX; + } + + return index; +} + +bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) +{ + if (nIndex == OS_INVALID_TLS_INDEX) { + assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); + return false; + } + + return PR_SetThreadPrivate(nIndex, lpvValue) == 0; +} + +bool OS_FreeTLSIndex(OS_TLSIndex nIndex) +{ + // Can't delete TLS keys with nspr + return true; +} + diff --git a/Source/ThirdParty/ANGLE/src/compiler/ossource_posix.cpp b/Source/ThirdParty/ANGLE/src/compiler/ossource_posix.cpp new file mode 100644 index 000000000..a21b0c23c --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/ossource_posix.cpp @@ -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. +// + +// +// 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; + } + 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; + 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; + 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 000000000..89922fef3 --- /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 000000000..9a8a50c31 --- /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 000000000..b4a7761ae --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/atom.c @@ -0,0 +1,736 @@ +/****************************************************************************\ +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); + while (stable->nextFree + len + 1 >= stable->size) { + assert(stable->size < 1000000); + str = (char *) malloc(stable->size*2); + memcpy(str, stable->strings, stable->size); + free(stable->strings); + stable->strings = str; + stable->size = stable->size*2; + } + loc = stable->nextFree; + strcpy(&stable->strings[loc], s); + stable->nextFree += len + 1; + return loc; +} // AddString + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////// Hash table: /////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +#define INIT_HASH_TABLE_SIZE 2047 +#define HASH_TABLE_MAX_COLLISIONS 3 + +typedef struct HashEntry_Rec { + int index; // String table offset of string representation + int value; // Atom (symbol) value +} HashEntry; + +typedef struct HashTable_Rec { + HashEntry *entry; + int size; + int entries; + int counts[HASH_TABLE_MAX_COLLISIONS + 1]; +} HashTable; + +/* + * InitHashTable() - Initialize the hash table. + * + */ + +static int InitHashTable(HashTable *htable, int fsize) +{ + int ii; + + htable->entry = (HashEntry *) malloc(sizeof(HashEntry)*fsize); + if (!htable->entry) + return 0; + htable->size = fsize; + for (ii = 0; ii < fsize; ii++) { + htable->entry[ii].index = 0; + htable->entry[ii].value = 0; + } + htable->entries = 0; + for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++) + htable->counts[ii] = 0; + return 1; +} // InitHashTable + +/* + * FreeHashTable() - Free the hash table. + * + */ + +static void FreeHashTable(HashTable *htable) +{ + if (htable->entry) + free(htable->entry); + htable->entry = NULL; + htable->size = 0; + htable->entries = 0; +} // FreeHashTable + +/* + * Empty() - See if a hash table entry is empty. + * + */ + +static int Empty(HashTable *htable, int hashloc) +{ + assert(hashloc >= 0 && hashloc < htable->size); + if (htable->entry[hashloc].index == 0) { + return 1; + } else { + return 0; + } +} // Empty + +/* + * Match() - See if a hash table entry is matches a string. + * + */ + +static int Match(HashTable *htable, StringTable *stable, const char *s, int hashloc) +{ + int strloc; + + strloc = htable->entry[hashloc].index; + if (!strcmp(s, &stable->strings[strloc])) { + return 1; + } else { + return 0; + } +} // Match + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////// Atom table: /////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +#define INIT_ATOM_TABLE_SIZE 1024 + + +struct AtomTable_Rec { + StringTable stable; // String table. + HashTable htable; // Hashes string to atom number and token value. Multiple strings can + // have the same token value but each unique string is a unique atom. + int *amap; // Maps atom value to offset in string table. Atoms all map to unique + // strings except for some undefined values in the lower, fixed part + // of the atom table that map to "<undefined>". The lowest 256 atoms + // correspond to single character ASCII values except for alphanumeric + // characters and '_', which can be other tokens. Next come the + // language tokens with their atom values equal to the token value. + // Then come predefined atoms, followed by user specified identifiers. + int *arev; // Reversed atom for symbol table use. + int nextFree; + int size; +}; + +static AtomTable latable = { { 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 000000000..1d84c3251 --- /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 000000000..11808531c --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/compile.h @@ -0,0 +1,100 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// compile.h +// + +#if !defined(__COMPILE_H) +#define __COMPILE_H 1 + +int InitCPPStruct(void); + +typedef struct Options_Rec{ + const char *profileString; + int ErrorMode; + int Quiet; + + // Debug The Compiler options: + int DumpAtomTable; +} Options; + +#define MAX_IF_NESTING 64 +struct CPPStruct_Rec { + // Public members + SourceLoc *pLastSourceLoc; // Set at the start of each statement by the tree walkers + Options options; // Compile options and parameters + + // Private members + SourceLoc lastSourceLoc; + + // Scanner data: + + SourceLoc *tokenLoc; // Source location of most recent token seen by the scanner + int mostRecentToken; // Most recent token seen by the scanner + InputSrc *currentInput; + int previous_token; + int pastFirstStatement; // used to make sure that #version is the first statement seen in the file, if present + + void *pC; // storing the parseContext of the compile object in cpp. + + // Private members: + SourceLoc ltokenLoc; + int ifdepth; //current #if-#else-#endif nesting in the cpp.c file (pre-processor) + int elsedepth[MAX_IF_NESTING];//Keep a track of #if depth..Max allowed is 64. + int elsetracker; //#if-#else and #endif constructs...Counter. + const char *ErrMsg; + int CompileError; //Indicate compile error when #error, #else,#elif mismatch. + + // + // Globals used to communicate between PaParseStrings() and yy_input()and + // also across the files.(gen_glslang.cpp and scanner.c) + // + int PaWhichStr; // which string we're parsing + const int* PaStrLen; // array of lengths of the PaArgv strings + int PaArgc; // count of strings in the array + const char* const* PaArgv; // our array of strings to parse + unsigned int tokensBeforeEOF : 1; +}; + +#endif // !defined(__COMPILE_H) diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.c b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.c new file mode 100644 index 000000000..03dd4f674 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.c @@ -0,0 +1,1114 @@ +/****************************************************************************\ +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 + +static SourceLoc ifloc; /* outermost #if */ + +int InitCPP(void) +{ + char buffer[64], *t; + const char *f; + + // Add various atoms needed by the CPP line scanner: + bindAtom = LookUpAddString(atable, "bind"); + constAtom = LookUpAddString(atable, "const"); + defaultAtom = LookUpAddString(atable, "default"); + defineAtom = LookUpAddString(atable, "define"); + definedAtom = LookUpAddString(atable, "defined"); + elifAtom = LookUpAddString(atable, "elif"); + elseAtom = LookUpAddString(atable, "else"); + endifAtom = LookUpAddString(atable, "endif"); + ifAtom = LookUpAddString(atable, "if"); + ifdefAtom = LookUpAddString(atable, "ifdef"); + ifndefAtom = LookUpAddString(atable, "ifndef"); + includeAtom = LookUpAddString(atable, "include"); + lineAtom = LookUpAddString(atable, "line"); + pragmaAtom = LookUpAddString(atable, "pragma"); + texunitAtom = LookUpAddString(atable, "texunit"); + undefAtom = LookUpAddString(atable, "undef"); + errorAtom = LookUpAddString(atable, "error"); + __LINE__Atom = LookUpAddString(atable, "__LINE__"); + __FILE__Atom = LookUpAddString(atable, "__FILE__"); + __VERSION__Atom = LookUpAddString(atable, "__VERSION__"); + versionAtom = LookUpAddString(atable, "version"); + extensionAtom = LookUpAddString(atable, "extension"); + macros = NewScopeInPool(mem_CreatePool(0, 0)); + strcpy(buffer, "PROFILE_"); + t = buffer + strlen(buffer); + f = cpp->options.profileString; + while ((isalnum(*f) || *f == '_') && t < buffer + sizeof(buffer) - 1) + *t++ = toupper(*f++); + *t = 0; + + PredefineIntMacro("GL_ES", 1); + PredefineIntMacro("GL_FRAGMENT_PRECISION_HIGH", 1); + + return 1; +} // InitCPP + +int FreeCPP(void) +{ + if (macros) + { + mem_FreePool(macros->pool); + macros = 0; + } + + return 1; +} + +int FinalCPP(void) +{ + if (cpp->ifdepth) + CPPErrorToInfoLog("#if mismatch"); + return 1; +} + +static int CPPdefine(yystypepp * yylvalpp) +{ + int token, name, args[MAX_MACRO_ARGS], argc; + const char *message; + MacroSymbol mac; + Symbol *symb; + SourceLoc dummyLoc; + memset(&mac, 0, sizeof(mac)); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != CPP_IDENTIFIER) { + CPPErrorToInfoLog("#define"); + return token; + } + name = yylvalpp->sc_ident; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token == '(' && !yylvalpp->sc_int) { + // gather arguments + argc = 0; + do { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (argc == 0 && token == ')') break; + if (token != CPP_IDENTIFIER) { + CPPErrorToInfoLog("#define"); + return token; + } + if (argc < MAX_MACRO_ARGS) + args[argc++] = yylvalpp->sc_ident; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } while (token == ','); + if (token != ')') { + CPPErrorToInfoLog("#define"); + return token; + } + mac.argc = argc; + mac.args = mem_Alloc(macros->pool, argc * sizeof(int)); + memcpy(mac.args, args, argc * sizeof(int)); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + mac.body = NewTokenStream(GetAtomString(atable, name), macros->pool); + while (token != '\n') { + if (token == '\\') { + CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language"); + return token; + } else if (token <= 0) { // EOF or error + CPPErrorToInfoLog("unexpected end of input in #define preprocessor directive - expected a newline"); + return 0; + } + RecordToken(mac.body, token, yylvalpp); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + }; + + symb = LookUpSymbol(macros, name); + if (symb) { + if (!symb->details.mac.undef) { + // already defined -- need to make sure they are identical + if (symb->details.mac.argc != mac.argc) goto error; + for (argc=0; argc < mac.argc; argc++) + if (symb->details.mac.args[argc] != mac.args[argc]) + goto error; + RewindTokenStream(symb->details.mac.body); + RewindTokenStream(mac.body); + do { + int old_lval, old_token; + old_token = ReadToken(symb->details.mac.body, yylvalpp); + old_lval = yylvalpp->sc_int; + token = ReadToken(mac.body, yylvalpp); + if (token != old_token || yylvalpp->sc_int != old_lval) { + error: + StoreStr("Macro Redefined"); + StoreStr(GetStringOfAtom(atable,name)); + message=GetStrfromTStr(); + DecLineNumber(); + CPPShInfoLogMsg(message); + IncLineNumber(); + ResetTString(); + break; } + } while (token > 0); + } + //FreeMacro(&symb->details.mac); + } else { + dummyLoc.file = 0; + dummyLoc.line = 0; + symb = AddSymbol(&dummyLoc, macros, name, MACRO_S); + } + symb->details.mac = mac; + return '\n'; +} // CPPdefine + +static int CPPundef(yystypepp * yylvalpp) +{ + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + Symbol *symb; + if(token == '\n'){ + CPPErrorToInfoLog("#undef"); + return token; + } + if (token != CPP_IDENTIFIER) + goto error; + symb = LookUpSymbol(macros, yylvalpp->sc_ident); + if (symb) { + symb->details.mac.undef = 1; + } + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != '\n') { + error: + CPPErrorToInfoLog("#undef"); + } + return token; +} // CPPundef + +/* CPPelse -- skip forward to appropriate spot. This is actually used +** to skip to and #endif after seeing an #else, AND to skip to a #else, +** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false +*/ + +static int CPPelse(int matchelse, yystypepp * yylvalpp) +{ + int atom,depth=0; + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + + while (token > 0) { + if (token != '#') { + while (token != '\n') { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token <= 0) { // EOF or error + CPPErrorToInfoLog("unexpected end of input in #else preprocessor directive - expected a newline"); + return 0; + } + } + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + continue; + } + if ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) != CPP_IDENTIFIER) + continue; + atom = yylvalpp->sc_ident; + if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom){ + depth++; cpp->ifdepth++; cpp->elsetracker++; + if (cpp->ifdepth > MAX_IF_NESTING) { + CPPErrorToInfoLog("max #if nesting depth exceeded"); + cpp->CompileError = 1; + return 0; + } + // sanity check elsetracker + if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) { + CPPErrorToInfoLog("mismatched #if/#endif statements"); + cpp->CompileError = 1; + return 0; + } + cpp->elsedepth[cpp->elsetracker] = 0; + } + else if (atom == endifAtom) { + if(--depth<0){ + if (cpp->elsetracker) + --cpp->elsetracker; + if (cpp->ifdepth) + --cpp->ifdepth; + break; + } + --cpp->elsetracker; + --cpp->ifdepth; + } + else if (((int)(matchelse) != 0)&& depth==0) { + if (atom == elseAtom ) { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != '\n') { + CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline"); + while (token != '\n') { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token <= 0) { // EOF or error + CPPErrorToInfoLog("unexpected end of input following #else preprocessor directive - expected a newline"); + return 0; + } + } + } + break; + } + else if (atom == elifAtom) { + /* we decrement cpp->ifdepth here, because CPPif will increment + * it and we really want to leave it alone */ + if (cpp->ifdepth){ + --cpp->ifdepth; + --cpp->elsetracker; + } + return CPPif(yylvalpp); + } + } + else if((atom==elseAtom) && (!ChkCorrectElseNesting())){ + CPPErrorToInfoLog("#else after a #else"); + cpp->CompileError=1; + return 0; + } + }; + return token; +} + +enum eval_prec { + MIN_PREC, + COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY, + MAX_PREC +}; + +static int op_logor(int a, int b) { return a || b; } +static int op_logand(int a, int b) { return a && b; } +static int op_or(int a, int b) { return a | b; } +static int op_xor(int a, int b) { return a ^ b; } +static int op_and(int a, int b) { return a & b; } +static int op_eq(int a, int b) { return a == b; } +static int op_ne(int a, int b) { return a != b; } +static int op_ge(int a, int b) { return a >= b; } +static int op_le(int a, int b) { return a <= b; } +static int op_gt(int a, int b) { return a > b; } +static int op_lt(int a, int b) { return a < b; } +static int op_shl(int a, int b) { return a << b; } +static int op_shr(int a, int b) { return a >> b; } +static int op_add(int a, int b) { return a + b; } +static int op_sub(int a, int b) { return a - b; } +static int op_mul(int a, int b) { return a * b; } +static int op_div(int a, int b) { return a / b; } +static int op_mod(int a, int b) { return a % b; } +static int op_pos(int a) { return a; } +static int op_neg(int a) { return -a; } +static int op_cmpl(int a) { return ~a; } +static int op_not(int a) { return !a; } + +struct { + int token, prec, (*op)(int, int); +} binop[] = { + { CPP_OR_OP, LOGOR, op_logor }, + { CPP_AND_OP, LOGAND, op_logand }, + { '|', OR, op_or }, + { '^', XOR, op_xor }, + { '&', AND, op_and }, + { CPP_EQ_OP, EQUAL, op_eq }, + { CPP_NE_OP, EQUAL, op_ne }, + { '>', RELATION, op_gt }, + { CPP_GE_OP, RELATION, op_ge }, + { '<', RELATION, op_lt }, + { CPP_LE_OP, RELATION, op_le }, + { CPP_LEFT_OP, SHIFT, op_shl }, + { CPP_RIGHT_OP, SHIFT, op_shr }, + { '+', ADD, op_add }, + { '-', ADD, op_sub }, + { '*', MUL, op_mul }, + { '/', MUL, op_div }, + { '%', MUL, op_mod }, +}; + +struct { + int token, (*op)(int); +} unop[] = { + { '+', op_pos }, + { '-', op_neg }, + { '~', op_cmpl }, + { '!', op_not }, +}; + +#define ALEN(A) (sizeof(A)/sizeof(A[0])) + +static int eval(int token, int prec, int *res, int *err, yystypepp * yylvalpp) +{ + int i, val; + Symbol *s; + if (token == CPP_IDENTIFIER) { + if (yylvalpp->sc_ident == definedAtom) { + int needclose = 0; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token == '(') { + needclose = 1; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + if (token != CPP_IDENTIFIER) + goto error; + *res = (s = LookUpSymbol(macros, yylvalpp->sc_ident)) + ? !s->details.mac.undef : 0; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (needclose) { + if (token != ')') + goto error; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + } else if (MacroExpand(yylvalpp->sc_ident, yylvalpp)) { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + return eval(token, prec, res, err, yylvalpp); + } else { + goto error; + } + } else if (token == CPP_INTCONSTANT) { + *res = yylvalpp->sc_int; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } else if (token == '(') { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + token = eval(token, MIN_PREC, res, err, yylvalpp); + if (!*err) { + if (token != ')') + goto error; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + } else { + for (i = ALEN(unop) - 1; i >= 0; i--) { + if (unop[i].token == token) + break; + } + if (i >= 0) { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + token = eval(token, UNARY, res, err, yylvalpp); + *res = unop[i].op(*res); + } else { + goto error; + } + } + while (!*err) { + if (token == ')' || token == '\n') break; + for (i = ALEN(binop) - 1; i >= 0; i--) { + if (binop[i].token == token) + break; + } + if (i < 0 || binop[i].prec <= prec) + break; + val = *res; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + token = eval(token, binop[i].prec, res, err, yylvalpp); + + if (binop[i].op == op_div || binop[i].op == op_mod) + { + if (*res == 0) + { + CPPErrorToInfoLog("preprocessor divide or modulo by zero"); + *err = 1; + return token; + } + } + + *res = binop[i].op(val, *res); + } + return token; +error: + CPPErrorToInfoLog("incorrect preprocessor directive"); + *err = 1; + *res = 0; + return token; +} // eval + +static int CPPif(yystypepp * yylvalpp) { + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + int res = 0, err = 0; + + if (!cpp->ifdepth++) + ifloc = *cpp->tokenLoc; + if(cpp->ifdepth > MAX_IF_NESTING){ + CPPErrorToInfoLog("max #if nesting depth exceeded"); + cpp->CompileError = 1; + return 0; + } + cpp->elsetracker++; + // sanity check elsetracker + if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) { + CPPErrorToInfoLog("mismatched #if/#endif statements"); + cpp->CompileError = 1; + return 0; + } + cpp->elsedepth[cpp->elsetracker] = 0; + + token = eval(token, MIN_PREC, &res, &err, yylvalpp); + if (token != '\n') { + CPPWarningToInfoLog("unexpected tokens following #if preprocessor directive - expected a newline"); + while (token != '\n') { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token <= 0) { // EOF or error + CPPErrorToInfoLog("unexpected end of input in #if preprocessor directive - expected a newline"); + return 0; + } + } + } + if (!res && !err) { + token = CPPelse(1, yylvalpp); + } + + return token; +} // CPPif + +static int CPPifdef(int defined, yystypepp * yylvalpp) +{ + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + int name = yylvalpp->sc_ident; + if(++cpp->ifdepth > MAX_IF_NESTING){ + CPPErrorToInfoLog("max #if nesting depth exceeded"); + cpp->CompileError = 1; + return 0; + } + cpp->elsetracker++; + // sanity check elsetracker + if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) { + CPPErrorToInfoLog("mismatched #if/#endif statements"); + cpp->CompileError = 1; + return 0; + } + cpp->elsedepth[cpp->elsetracker] = 0; + + if (token != CPP_IDENTIFIER) { + defined ? CPPErrorToInfoLog("ifdef"):CPPErrorToInfoLog("ifndef"); + } else { + Symbol *s = LookUpSymbol(macros, name); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != '\n') { + CPPWarningToInfoLog("unexpected tokens following #ifdef preprocessor directive - expected a newline"); + while (token != '\n') { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token <= 0) { // EOF or error + CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline"); + return 0; + } + } + } + if (((s && !s->details.mac.undef) ? 1 : 0) != defined) + token = CPPelse(1, yylvalpp); + } + return token; +} // CPPifdef + +static int CPPline(yystypepp * yylvalpp) +{ + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if(token=='\n'){ + DecLineNumber(); + CPPErrorToInfoLog("#line"); + IncLineNumber(); + return token; + } + else if (token == CPP_INTCONSTANT) { + yylvalpp->sc_int=atoi(yylvalpp->symbol_name); + SetLineNumber(yylvalpp->sc_int); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + + if (token == CPP_INTCONSTANT) { + yylvalpp->sc_int=atoi(yylvalpp->symbol_name); + SetStringNumber(yylvalpp->sc_int); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if(token!='\n') + CPPErrorToInfoLog("#line"); + } + else if (token == '\n'){ + return token; + } + else{ + CPPErrorToInfoLog("#line"); + } + } + else{ + CPPErrorToInfoLog("#line"); + } + return token; +} + +static int CPPerror(yystypepp * yylvalpp) { + + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + const char *message; + + while (token != '\n') { + if (token <= 0){ + CPPErrorToInfoLog("unexpected end of input in #error preprocessor directive - expected a newline"); + return 0; + }else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){ + StoreStr(yylvalpp->symbol_name); + }else if(token == CPP_IDENTIFIER || token == CPP_STRCONSTANT){ + StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident)); + }else { + StoreStr(GetStringOfAtom(atable,token)); + } + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + DecLineNumber(); + //store this msg into the shader's information log..set the Compile Error flag!!!! + message=GetStrfromTStr(); + CPPShInfoLogMsg(message); + ResetTString(); + cpp->CompileError=1; + IncLineNumber(); + return '\n'; +}//CPPerror + +static int CPPpragma(yystypepp * yylvalpp) +{ + char SrcStrName[2]; + char** allTokens; + int tokenCount = 0; + int maxTokenCount = 10; + const char* SrcStr; + int i; + + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + + if (token=='\n') { + DecLineNumber(); + CPPErrorToInfoLog("#pragma"); + IncLineNumber(); + return token; + } + + allTokens = (char**)malloc(sizeof(char*) * maxTokenCount); + + while (token != '\n') { + if (tokenCount >= maxTokenCount) { + maxTokenCount *= 2; + allTokens = (char**)realloc((char**)allTokens, sizeof(char*) * maxTokenCount); + } + switch (token) { + case CPP_IDENTIFIER: + SrcStr = GetAtomString(atable, yylvalpp->sc_ident); + allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); + strcpy(allTokens[tokenCount++], SrcStr); + break; + case CPP_INTCONSTANT: + SrcStr = yylvalpp->symbol_name; + allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); + strcpy(allTokens[tokenCount++], SrcStr); + break; + case CPP_FLOATCONSTANT: + SrcStr = yylvalpp->symbol_name; + allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); + strcpy(allTokens[tokenCount++], SrcStr); + break; + case -1: + // EOF + CPPShInfoLogMsg("#pragma directive must end with a newline"); + 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[MAX_SYMBOL_NAME_LEN + 1]; + + if(token=='\n'){ + DecLineNumber(); + CPPShInfoLogMsg("extension name not specified"); + IncLineNumber(); + return token; + } + + if (token != CPP_IDENTIFIER) + CPPErrorToInfoLog("#extension"); + + strncpy(extensionName, GetAtomString(atable, yylvalpp->sc_ident), MAX_SYMBOL_NAME_LEN); + extensionName[MAX_SYMBOL_NAME_LEN] = '\0'; + + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != ':') { + CPPShInfoLogMsg("':' missing after extension name"); + return token; + } + + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != CPP_IDENTIFIER) { + CPPShInfoLogMsg("behavior for extension not specified"); + return token; + } + + updateExtensionBehavior(extensionName, GetAtomString(atable, yylvalpp->sc_ident)); + + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token == '\n'){ + return token; + } + else{ + CPPErrorToInfoLog("#extension"); + } + return token; +} // CPPextension + +int readCPPline(yystypepp * yylvalpp) +{ + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + const char *message; + 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; + return 0; + } + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != '\n') { + CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline"); + while (token != '\n') { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token <= 0) { // EOF or error + CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline"); + return 0; + } + } + } + token = CPPelse(0, yylvalpp); + }else{ + CPPErrorToInfoLog("#else after a #else"); + cpp->ifdepth = 0; + cpp->elsetracker = 0; + cpp->pastFirstStatement = 1; + cpp->CompileError = 1; + return 0; + } + } else if (yylvalpp->sc_ident == elifAtom) { + if (!cpp->ifdepth){ + CPPErrorToInfoLog("#elif mismatch"); + cpp->CompileError=1; + return 0; + } + // this token is really a dont care, but we still need to eat the tokens + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + while (token != '\n') { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token <= 0) { // EOF or error + CPPErrorToInfoLog("unexpect tokens following #elif preprocessor directive - expected a newline"); + cpp->CompileError = 1; + return 0; + } + } + token = CPPelse(0, yylvalpp); + } else if (yylvalpp->sc_ident == endifAtom) { + if (!cpp->ifdepth){ + CPPErrorToInfoLog("#endif mismatch"); + cpp->CompileError=1; + return 0; + } + else + --cpp->ifdepth; + + if (cpp->elsetracker) + --cpp->elsetracker; + + } else if (yylvalpp->sc_ident == ifAtom) { + token = CPPif(yylvalpp); + } else if (yylvalpp->sc_ident == ifdefAtom) { + token = CPPifdef(1, yylvalpp); + } else if (yylvalpp->sc_ident == ifndefAtom) { + token = CPPifdef(0, yylvalpp); + } else if (yylvalpp->sc_ident == lineAtom) { + token = CPPline(yylvalpp); + } else if (yylvalpp->sc_ident == pragmaAtom) { + token = CPPpragma(yylvalpp); + } else if (yylvalpp->sc_ident == undefAtom) { + token = CPPundef(yylvalpp); + } else if (yylvalpp->sc_ident == errorAtom) { + token = CPPerror(yylvalpp); + } else if (yylvalpp->sc_ident == versionAtom) { + token = CPPversion(yylvalpp); + 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) +{ + // sanity check to make sure elsetracker is in a valid range + if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) { + return 0; + } + + if (cpp->elsedepth[cpp->elsetracker] == 0) { + cpp->elsedepth[cpp->elsetracker] = 1; + return 1; + } + return 0; +} + + diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.h b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.h new file mode 100644 index 000000000..db4c184ae --- /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 000000000..58cff3109 --- /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 < MAX_IF_NESTING; cpp->elsetracker++) + cpp->elsedepth[cpp->elsetracker] = 0; + cpp->elsetracker = 0; + cpp->tokensBeforeEOF = 0; + return 1; +} + +//Intializing the Preprocessor. + +int InitPreprocessor(void) +{ + # define CPP_STUFF true + # ifdef CPP_STUFF + FreeCPPStruct(); + InitCPPStruct(); + cpp->options.Quiet = 1; + cpp->options.profileString = "generic"; + if (!InitAtomTable(atable, 0)) + return 1; + if (!InitScanner(cpp)) + return 1; + # endif + return 0; +} + +//FreeCPPStruct() - Free the CPP structure. + +int FreeCPPStruct(void) +{ + if (refCount) + { + free(cpp); + refCount--; + } + + return 1; +} + +//Finalizing the Preprocessor. + +int FinalizePreprocessor(void) +{ + # define CPP_STUFF true + # ifdef CPP_STUFF + FreeAtomTable(atable); + FreeCPPStruct(); + FreeScanner(); + # endif + return 0; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////// End of cppstruct.c ////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/memory.c b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/memory.c new file mode 100644 index 000000000..e6fea7aa3 --- /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 000000000..b3ae2f963 --- /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 000000000..f67342b67 --- /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 000000000..88d196ffe --- /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(const 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 000000000..deedb43f5 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/scanner.c @@ -0,0 +1,688 @@ +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// scanner.c +// + +#include <assert.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#if 0 + #include <ieeefp.h> +#else + #define isinff(x) (((*(int *)&(x) & 0x7f800000L)==0x7f800000L) && \ + ((*(int *)&(x) & 0x007fffffL)==0000000000L)) +#endif + +#include "compiler/preprocessor/slglobals.h" +#include "compiler/util.h" + +typedef struct StringInputSrc { + InputSrc base; + char *p; +} StringInputSrc; + +static int 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(const char *s) +{ + + StringInputSrc *in = malloc(sizeof(StringInputSrc)); + memset(in, 0, sizeof(StringInputSrc)); + in->p = (char*) s; + in->base.line = 1; + in->base.scan = byte_scan; + in->base.getch = (int (*)(InputSrc *, yystypepp *))str_getch; + in->base.ungetch = (void (*)(InputSrc *, int, yystypepp *))str_ungetch; + in->base.prev = cpp->currentInput; + cpp->currentInput = &in->base; + + return 1; +} // ScanFromString; + + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////// Floating point constants: ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +#define APPEND_CHAR_S(ch, str, len, max_len) \ + if (len < max_len) { \ + str[len++] = ch; \ + } else if (!alreadyComplained) { \ + CPPErrorToInfoLog("BUFFER OVERFLOW"); \ + alreadyComplained = 1; \ + } + +/* + * lFloatConst() - Scan a floating point constant. Assumes that the scanner + * has seen at least one digit, followed by either a decimal '.' or the + * letter 'e'. + * ch - '.' or 'e' + * len - length of string already copied into yylvalpp->symbol_name. + */ + +static int lFloatConst(int ch, int len, yystypepp * yylvalpp) +{ + int alreadyComplained = 0; + assert((ch == '.') || (ch == 'e') || (ch == 'E')); + + if (ch == '.') { + do { + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } while (ch >= '0' && ch <= '9'); + } + + // Exponent: + if (ch == 'e' || ch == 'E') { + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '+') { + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } else if (ch == '-') { + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } + if (ch >= '0' && ch <= '9') { + while (ch >= '0' && ch <= '9') { + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } + } else { + CPPErrorToInfoLog("EXPONENT INVALID"); + } + } + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + + assert(len <= MAX_SYMBOL_NAME_LEN); + yylvalpp->symbol_name[len] = '\0'; + yylvalpp->sc_fval = (float) atof_dot(yylvalpp->symbol_name); + if (isinff(yylvalpp->sc_fval)) { + CPPErrorToInfoLog("FLOAT CONSTANT OVERFLOW"); + } + return CPP_FLOATCONSTANT; +} // lFloatConst + +/////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////// Normal Scanner ////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +static int byte_scan(InputSrc *in, yystypepp * yylvalpp) +{ + char string_val[MAX_STRING_LEN + 1]; + int alreadyComplained = 0; + int len, ch, ii, ival = 0; + + for (;;) { + yylvalpp->sc_int = 0; + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + + while (ch == ' ' || ch == '\t' || ch == '\r') { + yylvalpp->sc_int = 1; + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } + + cpp->ltokenLoc.file = cpp->currentInput->name; + cpp->ltokenLoc.line = cpp->currentInput->line; + alreadyComplained = 0; + len = 0; + switch (ch) { + default: + return ch; // Single character token + case EOF: + return -1; + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': case '_': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': + do { + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } while ((ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || + (ch >= '0' && ch <= '9') || + ch == '_'); + assert(len <= MAX_SYMBOL_NAME_LEN); + yylvalpp->symbol_name[len] = '\0'; + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + yylvalpp->sc_ident = LookUpAddString(atable, yylvalpp->symbol_name); + return CPP_IDENTIFIER; + break; + case '0': + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == 'x' || ch == 'X') { // hexadecimal integer constants + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if ((ch >= '0' && ch <= '9') || + (ch >= 'A' && ch <= 'F') || + (ch >= 'a' && ch <= 'f')) + { + ival = 0; + do { + if ((ival <= 0x0fffffff) && (len < MAX_SYMBOL_NAME_LEN)) { + yylvalpp->symbol_name[len++] = ch; + if (ch >= '0' && ch <= '9') { + ii = ch - '0'; + } else if (ch >= 'A' && ch <= 'F') { + ii = ch - 'A' + 10; + } else { + ii = ch - 'a' + 10; + } + ival = (ival << 4) | ii; + } else if (!alreadyComplained) { + CPPErrorToInfoLog("HEX CONSTANT OVERFLOW"); + alreadyComplained = 1; + } + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } while ((ch >= '0' && ch <= '9') || + (ch >= 'A' && ch <= 'F') || + (ch >= 'a' && ch <= 'f')); + } else { + CPPErrorToInfoLog("HEX CONSTANT INVALID"); + } + assert(len <= MAX_SYMBOL_NAME_LEN); + yylvalpp->symbol_name[len] = '\0'; + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + yylvalpp->sc_int = ival; + return CPP_INTCONSTANT; + } else if (ch >= '0' && ch <= '7') { // octal integer constants + ival = 0; + do { + if ((ival <= 0x1fffffff) && (len < MAX_SYMBOL_NAME_LEN)) { + yylvalpp->symbol_name[len++] = ch; + ii = ch - '0'; + ival = (ival << 3) | ii; + } else if (!alreadyComplained) { + CPPErrorToInfoLog("OCT CONSTANT OVERFLOW"); + alreadyComplained = 1; + } + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } while (ch >= '0' && ch <= '7'); + if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') + return lFloatConst(ch, len, yylvalpp); + assert(len <= MAX_SYMBOL_NAME_LEN); + yylvalpp->symbol_name[len] = '\0'; + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + yylvalpp->sc_int = ival; + return CPP_INTCONSTANT; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + ch = '0'; + } + // Fall through... + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + do { + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } while (ch >= '0' && ch <= '9'); + if (ch == '.' || ch == 'e' || ch == 'E') { + return lFloatConst(ch, len, yylvalpp); + } else { + assert(len <= MAX_SYMBOL_NAME_LEN); + yylvalpp->symbol_name[len] = '\0'; + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + ival = 0; + for (ii = 0; ii < len; ii++) { + ch = yylvalpp->symbol_name[ii] - '0'; + ival = ival*10 + ch; + if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) { + CPPErrorToInfoLog("INTEGER CONSTANT OVERFLOW"); + break; + } + } + yylvalpp->sc_int = ival; + if(ival==0) + strcpy(yylvalpp->symbol_name,"0"); + return CPP_INTCONSTANT; + } + break; + case '-': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '-') { + return CPP_DEC_OP; + } else if (ch == '=') { + return CPP_SUB_ASSIGN; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '-'; + } + case '+': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '+') { + return CPP_INC_OP; + } else if (ch == '=') { + return CPP_ADD_ASSIGN; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '+'; + } + case '*': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '=') { + return CPP_MUL_ASSIGN; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '*'; + } + case '%': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '=') { + return CPP_MOD_ASSIGN; + } else if (ch == '>'){ + return CPP_RIGHT_BRACE; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '%'; + } + case ':': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '>') { + return CPP_RIGHT_BRACKET; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return ':'; + } + case '^': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '^') { + return CPP_XOR_OP; + } else { + if (ch == '=') + return CPP_XOR_ASSIGN; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '^'; + } + } + + case '=': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '=') { + return CPP_EQ_OP; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '='; + } + case '!': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '=') { + return CPP_NE_OP; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '!'; + } + case '|': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '|') { + return CPP_OR_OP; + } else { + if (ch == '=') + return CPP_OR_ASSIGN; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '|'; + } + } + case '&': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '&') { + return CPP_AND_OP; + } else { + if (ch == '=') + return CPP_AND_ASSIGN; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '&'; + } + } + case '<': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '<') { + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if(ch == '=') + return CPP_LEFT_ASSIGN; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return CPP_LEFT_OP; + } + } else { + if (ch == '=') { + return CPP_LE_OP; + } else { + if (ch == '%') + return CPP_LEFT_BRACE; + else if (ch == ':') + return CPP_LEFT_BRACKET; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '<'; + } + } + } + case '>': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '>') { + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if(ch == '=') + return CPP_RIGHT_ASSIGN; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return CPP_RIGHT_OP; + } + } else { + if (ch == '=') { + return CPP_GE_OP; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '>'; + } + } + case '.': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch >= '0' && ch <= '9') { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return lFloatConst('.', 0, yylvalpp); + } else { + if (ch == '.') { + return -1; // Special EOF hack + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '.'; + } + } + case '/': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '/') { + do { + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } while (ch != '\n' && ch != EOF); + if (ch == EOF) + return -1; + return '\n'; + } else if (ch == '*') { + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + do { + while (ch != '*') { + if (ch == EOF) { + CPPErrorToInfoLog("EOF IN COMMENT"); + return -1; + } + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == EOF) { + CPPErrorToInfoLog("EOF IN COMMENT"); + return -1; + } + } while (ch != '/'); + // Go try it again... + } else if (ch == '=') { + return CPP_DIV_ASSIGN; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '/'; + } + break; + case '"': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + while (ch != '"' && ch != '\n' && ch != EOF) { + if (ch == '\\') { + CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language"); + return -1; + } + APPEND_CHAR_S(ch, string_val, len, MAX_STRING_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + }; + assert(len <= MAX_STRING_LEN); + string_val[len] = '\0'; + if (ch == '"') { + yylvalpp->sc_ident = LookUpAddString(atable, string_val); + return CPP_STRCONSTANT; + } else { + CPPErrorToInfoLog("EOL IN STRING"); + return ERROR_SY; + } + break; + } + } +} // byte_scan + +int yylex_CPP(char* buf, int maxSize) +{ + yystypepp yylvalpp; + int token = '\n'; + + for(;;) { + + char* tokenString = 0; + token = cpp->currentInput->scan(cpp->currentInput, &yylvalpp); + if(check_EOF(token)) + return 0; + if (token < 0) { + // This check may need to be improved to support UTF-8 + // characters in comments. + CPPErrorToInfoLog("preprocessor encountered non-ASCII character in shader source"); + return 0; + } + if (token == '#') { + if (cpp->previous_token == '\n'|| cpp->previous_token == 0) { + token = readCPPline(&yylvalpp); + if(check_EOF(token)) + return 0; + continue; + } else { + CPPErrorToInfoLog("preprocessor command must not be preceded by any other statement in that line"); + return 0; + } + } + cpp->previous_token = token; + // expand macros + if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp.sc_ident, &yylvalpp)) { + cpp->pastFirstStatement = 1; + continue; + } + + if (token == '\n') + continue; + cpp->pastFirstStatement = 1; + + if (token == CPP_IDENTIFIER) { + tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident); + } else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){ + tokenString = yylvalpp.symbol_name; + } else { + tokenString = GetStringOfAtom(atable,token); + } + + if (tokenString) { + int len = strlen(tokenString); + cpp->tokensBeforeEOF = 1; + if (len >= maxSize) { + return maxSize; + } else if (len > 0) { + strcpy(buf, tokenString); + return len; + } + + return 0; + } + } + + 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 000000000..33306e523 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/scanner.h @@ -0,0 +1,84 @@ +/****************************************************************************\ +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 + +// These lengths do not include the NULL terminator. +#define MAX_SYMBOL_NAME_LEN 256 +#define MAX_STRING_LEN 511 + +#include "compiler/preprocessor/parser.h" + +// Not really atom table stuff but needed first... + +typedef struct SourceLoc_Rec { + unsigned short file, line; +} SourceLoc; + +int yylex_CPP(char* buf, int maxSize); + +typedef struct InputSrc { + struct InputSrc *prev; + int (*scan)(struct InputSrc *, yystypepp *); + int (*getch)(struct InputSrc *, yystypepp *); + void (*ungetch)(struct InputSrc *, int, yystypepp *); + int name; /* atom */ + int line; +} InputSrc; + +int InitScanner(CPPStruct *cpp); // Intialise the cpp scanner. +int ScanFromString(const 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 000000000..463462664 --- /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 000000000..5baedf52f --- /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 000000000..c19f79c97 --- /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 000000000..aa83d2fce --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/tokens.c @@ -0,0 +1,436 @@ +/****************************************************************************\ +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" +#include "compiler/util.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++); + } + 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; + ch = lReadByte(pTok); + } + } + symbol_name[len] = '\0'; + assert(ch == '\0'); + yylvalpp->sc_ident = LookUpAddString(atable, symbol_name); + return CPP_IDENTIFIER; + break; + case CPP_STRCONSTANT: + len = 0; + while ((ch = lReadByte(pTok)) != 0) + if (len < MAX_STRING_LEN) + string_val[len++] = ch; + string_val[len] = '\0'; + yylvalpp->sc_ident = LookUpAddString(atable, string_val); + break; + case CPP_FLOATCONSTANT: + len = 0; + ch = lReadByte(pTok); + while ((ch >= '0' && ch <= '9')||(ch=='e'||ch=='E'||ch=='.')||(ch=='+'||ch=='-')) + { + if (len < MAX_SYMBOL_NAME_LEN) { + symbol_name[len++] = ch; + ch = lReadByte(pTok); + } + } + symbol_name[len] = '\0'; + assert(ch == '\0'); + strcpy(yylvalpp->symbol_name,symbol_name); + yylvalpp->sc_fval=(float)atof_dot(yylvalpp->symbol_name); + break; + case CPP_INTCONSTANT: + len = 0; + ch = lReadByte(pTok); + while ((ch >= '0' && ch <= '9')) + { + if (len < MAX_SYMBOL_NAME_LEN) { + symbol_name[len++] = ch; + ch = lReadByte(pTok); + } + } + symbol_name[len] = '\0'; + assert(ch == '\0'); + strcpy(yylvalpp->symbol_name,symbol_name); + yylvalpp->sc_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 000000000..8766df9e4 --- /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/util.cpp b/Source/ThirdParty/ANGLE/src/compiler/util.cpp new file mode 100644 index 000000000..b46e4d0e3 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/util.cpp @@ -0,0 +1,33 @@ +// +// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include <math.h> +#include <stdlib.h> + +#include "util.h" + +#ifdef _MSC_VER + #include <locale.h> +#else + #include <sstream> +#endif + +double atof_dot(const char *str) +{ +#ifdef _MSC_VER + _locale_t l = _create_locale(LC_NUMERIC, "C"); + double result = _atof_l(str, l); + _free_locale(l); + return result; +#else + double result; + std::istringstream s(str); + std::locale l("C"); + s.imbue(l); + s >> result; + return result; +#endif +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/util.h b/Source/ThirdParty/ANGLE/src/compiler/util.h new file mode 100644 index 000000000..35288b739 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/util.h @@ -0,0 +1,21 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_UTIL_H +#define COMPILER_UTIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +// atof_dot is like atof but forcing C locale, i.e. forcing '.' as decimal point. +double atof_dot(const char *str); + +#ifdef __cplusplus +} // end extern "C" +#endif + +#endif // COMPILER_UTIL_H diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Config.cpp b/Source/ThirdParty/ANGLE/src/libEGL/Config.cpp new file mode 100644 index 000000000..e4dc704a9 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libEGL/Config.cpp @@ -0,0 +1,399 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Config.cpp: Implements the egl::Config class, describing the format, type +// and size for an egl::Surface. Implements EGLConfig and related functionality. +// [EGL 1.4] section 3.4 page 15. + +#include "libEGL/Config.h" + +#include <algorithm> +#include <vector> + +#include "common/debug.h" + +using namespace std; + +namespace egl +{ +Config::Config(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight) + : mDisplayMode(displayMode), mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample) +{ + set(displayMode, minInterval, maxInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight); +} + +void Config::setDefaults() +{ + mBufferSize = 0; + mRedSize = 0; + mGreenSize = 0; + mBlueSize = 0; + mLuminanceSize = 0; + mAlphaSize = 0; + mAlphaMaskSize = 0; + mBindToTextureRGB = EGL_DONT_CARE; + mBindToTextureRGBA = EGL_DONT_CARE; + mColorBufferType = EGL_RGB_BUFFER; + mConfigCaveat = EGL_DONT_CARE; + mConfigID = EGL_DONT_CARE; + mConformant = 0; + mDepthSize = 0; + mLevel = 0; + mMatchNativePixmap = EGL_NONE; + mMaxPBufferWidth = 0; + mMaxPBufferHeight = 0; + mMaxPBufferPixels = 0; + mMaxSwapInterval = EGL_DONT_CARE; + mMinSwapInterval = EGL_DONT_CARE; + mNativeRenderable = EGL_DONT_CARE; + mNativeVisualID = 0; + mNativeVisualType = EGL_DONT_CARE; + mRenderableType = EGL_OPENGL_ES_BIT; + mSampleBuffers = 0; + mSamples = 0; + mStencilSize = 0; + mSurfaceType = EGL_WINDOW_BIT; + mTransparentType = EGL_NONE; + mTransparentRedValue = EGL_DONT_CARE; + mTransparentGreenValue = EGL_DONT_CARE; + mTransparentBlueValue = EGL_DONT_CARE; +} + +void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight) +{ + mBindToTextureRGB = EGL_FALSE; + mBindToTextureRGBA = EGL_FALSE; + switch (renderTargetFormat) + { + case D3DFMT_A1R5G5B5: + mBufferSize = 16; + mRedSize = 5; + mGreenSize = 5; + mBlueSize = 5; + mAlphaSize = 1; + break; + case D3DFMT_A2R10G10B10: + mBufferSize = 32; + mRedSize = 10; + mGreenSize = 10; + mBlueSize = 10; + mAlphaSize = 2; + break; + case D3DFMT_A8R8G8B8: + mBufferSize = 32; + mRedSize = 8; + mGreenSize = 8; + mBlueSize = 8; + mAlphaSize = 8; + mBindToTextureRGBA = true; + break; + case D3DFMT_R5G6B5: + mBufferSize = 16; + mRedSize = 5; + mGreenSize = 6; + mBlueSize = 5; + mAlphaSize = 0; + break; + case D3DFMT_X8R8G8B8: + mBufferSize = 32; + mRedSize = 8; + mGreenSize = 8; + mBlueSize = 8; + mAlphaSize = 0; + mBindToTextureRGB = true; + break; + default: + UNREACHABLE(); // Other formats should not be valid + } + + mLuminanceSize = 0; + mAlphaMaskSize = 0; + mColorBufferType = EGL_RGB_BUFFER; + mConfigCaveat = (displayMode.Format == renderTargetFormat) ? EGL_NONE : EGL_SLOW_CONFIG; + mConfigID = 0; + mConformant = EGL_OPENGL_ES2_BIT; + + switch (depthStencilFormat) + { + case D3DFMT_UNKNOWN: + mDepthSize = 0; + mStencilSize = 0; + break; +// case D3DFMT_D16_LOCKABLE: +// mDepthSize = 16; +// mStencilSize = 0; +// break; + case D3DFMT_D32: + mDepthSize = 32; + mStencilSize = 0; + break; + case D3DFMT_D15S1: + mDepthSize = 15; + mStencilSize = 1; + break; + case D3DFMT_D24S8: + mDepthSize = 24; + mStencilSize = 8; + break; + case D3DFMT_D24X8: + mDepthSize = 24; + mStencilSize = 0; + break; + case D3DFMT_D24X4S4: + mDepthSize = 24; + mStencilSize = 4; + break; + case D3DFMT_D16: + mDepthSize = 16; + mStencilSize = 0; + break; +// case D3DFMT_D32F_LOCKABLE: +// mDepthSize = 32; +// mStencilSize = 0; +// break; +// case D3DFMT_D24FS8: +// mDepthSize = 24; +// mStencilSize = 8; +// break; + default: + UNREACHABLE(); + } + + mLevel = 0; + mMatchNativePixmap = EGL_NONE; + mMaxPBufferWidth = texWidth; + mMaxPBufferHeight = texHeight; + mMaxPBufferPixels = texWidth*texHeight; + mMaxSwapInterval = maxInterval; + mMinSwapInterval = minInterval; + mNativeRenderable = EGL_FALSE; + mNativeVisualID = 0; + mNativeVisualType = 0; + mRenderableType = EGL_OPENGL_ES2_BIT; + mSampleBuffers = multiSample ? 1 : 0; + mSamples = multiSample; + mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; + mTransparentType = EGL_NONE; + mTransparentRedValue = 0; + mTransparentGreenValue = 0; + mTransparentBlueValue = 0; +} + +EGLConfig Config::getHandle() const +{ + return (EGLConfig)(size_t)mConfigID; +} + +SortConfig::SortConfig(const EGLint *attribList) + : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false) +{ + scanForWantedComponents(attribList); +} + +void SortConfig::scanForWantedComponents(const EGLint *attribList) +{ + // [EGL] section 3.4.1 page 24 + // Sorting rule #3: by larger total number of color bits, not considering + // components that are 0 or don't-care. + for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2) + { + if (attr[1] != 0 && attr[1] != EGL_DONT_CARE) + { + switch (attr[0]) + { + case EGL_RED_SIZE: mWantRed = true; break; + case EGL_GREEN_SIZE: mWantGreen = true; break; + case EGL_BLUE_SIZE: mWantBlue = true; break; + case EGL_ALPHA_SIZE: mWantAlpha = true; break; + case EGL_LUMINANCE_SIZE: mWantLuminance = true; break; + } + } + } +} + +EGLint SortConfig::wantedComponentsSize(const Config &config) const +{ + EGLint total = 0; + + if (mWantRed) total += config.mRedSize; + if (mWantGreen) total += config.mGreenSize; + if (mWantBlue) total += config.mBlueSize; + if (mWantAlpha) total += config.mAlphaSize; + if (mWantLuminance) total += config.mLuminanceSize; + + return total; +} + +bool SortConfig::operator()(const Config *x, const Config *y) const +{ + return (*this)(*x, *y); +} + +bool SortConfig::operator()(const Config &x, const Config &y) const +{ + #define SORT(attribute) \ + if (x.attribute != y.attribute) \ + { \ + return x.attribute < y.attribute; \ + } + + META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG); + SORT(mConfigCaveat); + + META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER); + SORT(mColorBufferType); + + // By larger total number of color bits, only considering those that are requested to be > 0. + EGLint xComponentsSize = wantedComponentsSize(x); + EGLint yComponentsSize = wantedComponentsSize(y); + if (xComponentsSize != yComponentsSize) + { + return xComponentsSize > yComponentsSize; + } + + SORT(mBufferSize); + SORT(mSampleBuffers); + SORT(mSamples); + SORT(mDepthSize); + SORT(mStencilSize); + SORT(mAlphaMaskSize); + SORT(mNativeVisualType); + SORT(mConfigID); + + #undef SORT + + return false; +} + +// We'd like to use SortConfig to also eliminate duplicate configs. +// This works as long as we never have two configs with different per-RGB-component layouts, +// but the same total. +// 5551 and 565 are different because R+G+B is different. +// 5551 and 555 are different because bufferSize is different. +const EGLint ConfigSet::mSortAttribs[] = +{ + EGL_RED_SIZE, 1, + EGL_GREEN_SIZE, 1, + EGL_BLUE_SIZE, 1, + EGL_LUMINANCE_SIZE, 1, + // BUT NOT ALPHA + EGL_NONE +}; + +ConfigSet::ConfigSet() + : mSet(SortConfig(mSortAttribs)) +{ +} + +void ConfigSet::add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight) +{ + Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight); + + mSet.insert(config); +} + +size_t ConfigSet::size() const +{ + return mSet.size(); +} + +bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig) +{ + vector<const Config*> passed; + passed.reserve(mSet.size()); + + for (Iterator config = mSet.begin(); config != mSet.end(); config++) + { + bool match = true; + const EGLint *attribute = attribList; + + while (attribute[0] != EGL_NONE) + { + switch (attribute[0]) + { + case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break; + case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break; + case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break; + case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break; + case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break; + case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break; + case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break; + case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == attribute[1]; break; + case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break; + case EGL_LEVEL: match = config->mLevel >= attribute[1]; break; + case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == attribute[1]; break; + case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break; + case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break; + case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break; + case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break; + case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == attribute[1]; break; + case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break; + case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break; + case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break; + case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == attribute[1]; break; + case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == attribute[1]; break; + case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break; + case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break; + case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break; + case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break; + case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == attribute[1]; break; + case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break; + case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break; + case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break; + case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break; + case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break; + case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break; + default: + return false; + } + + if (!match) + { + break; + } + + attribute += 2; + } + + if (match) + { + passed.push_back(&*config); + } + } + + if (configs) + { + sort(passed.begin(), passed.end(), SortConfig(attribList)); + + EGLint index; + for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++) + { + configs[index] = passed[index]->getHandle(); + } + + *numConfig = index; + } + else + { + *numConfig = passed.size(); + } + + return true; +} + +const egl::Config *ConfigSet::get(EGLConfig configHandle) +{ + for (Iterator config = mSet.begin(); config != mSet.end(); config++) + { + if (config->getHandle() == configHandle) + { + return &(*config); + } + } + + return NULL; +} +} diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Config.h b/Source/ThirdParty/ANGLE/src/libEGL/Config.h new file mode 100644 index 000000000..95626ed1a --- /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, EGLint texWidth, EGLint texHeight); + + void setDefaults(); + void set(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight); + EGLConfig getHandle() const; + + const D3DDISPLAYMODE mDisplayMode; + const D3DFORMAT mRenderTargetFormat; + const D3DFORMAT mDepthStencilFormat; + const EGLint mMultiSample; + + EGLint mBufferSize; // Depth of the color buffer + EGLint mRedSize; // Bits of Red in the color buffer + EGLint mGreenSize; // Bits of Green in the color buffer + EGLint mBlueSize; // Bits of Blue in the color buffer + EGLint mLuminanceSize; // Bits of Luminance in the color buffer + EGLint mAlphaSize; // Bits of Alpha in the color buffer + EGLint mAlphaMaskSize; // Bits of Alpha Mask in the mask buffer + EGLBoolean mBindToTextureRGB; // True if bindable to RGB textures. + EGLBoolean mBindToTextureRGBA; // True if bindable to RGBA textures. + EGLenum mColorBufferType; // Color buffer type + EGLenum mConfigCaveat; // Any caveats for the configuration + EGLint mConfigID; // Unique EGLConfig identifier + EGLint mConformant; // Whether contexts created with this config are conformant + EGLint mDepthSize; // Bits of Z in the depth buffer + EGLint mLevel; // Frame buffer level + EGLBoolean mMatchNativePixmap; // Match the native pixmap format + EGLint mMaxPBufferWidth; // Maximum width of pbuffer + EGLint mMaxPBufferHeight; // Maximum height of pbuffer + EGLint mMaxPBufferPixels; // Maximum size of pbuffer + EGLint mMaxSwapInterval; // Maximum swap interval + EGLint mMinSwapInterval; // Minimum swap interval + EGLBoolean mNativeRenderable; // EGL_TRUE if native rendering APIs can render to surface + EGLint mNativeVisualID; // Handle of corresponding native visual + EGLint mNativeVisualType; // Native visual type of the associated visual + EGLint mRenderableType; // Which client rendering APIs are supported. + EGLint mSampleBuffers; // Number of multisample buffers + EGLint mSamples; // Number of samples per pixel + EGLint mStencilSize; // Bits of Stencil in the stencil buffer + EGLint mSurfaceType; // Which types of EGL surfaces are supported. + EGLenum mTransparentType; // Type of transparency supported + EGLint mTransparentRedValue; // Transparent red value + EGLint mTransparentGreenValue; // Transparent green value + EGLint mTransparentBlueValue; // Transparent blue value +}; + +// Function object used by STL sorting routines for ordering Configs according to [EGL] section 3.4.1 page 24. +class SortConfig +{ + public: + explicit SortConfig(const EGLint *attribList); + + bool operator()(const Config *x, const Config *y) const; + bool operator()(const Config &x, const Config &y) const; + + private: + void scanForWantedComponents(const EGLint *attribList); + EGLint wantedComponentsSize(const Config &config) const; + + bool mWantRed; + bool mWantGreen; + bool mWantBlue; + bool mWantAlpha; + bool mWantLuminance; +}; + +class ConfigSet +{ + friend Display; + + public: + ConfigSet(); + + void add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight); + size_t size() const; + bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig); + const egl::Config *get(EGLConfig configHandle); + + private: + DISALLOW_COPY_AND_ASSIGN(ConfigSet); + + typedef std::set<Config, SortConfig> Set; + typedef Set::iterator Iterator; + Set mSet; + + static const EGLint mSortAttribs[]; +}; +} + +#endif // INCLUDE_CONFIG_H_ diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp b/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp new file mode 100644 index 000000000..1d64f9a10 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp @@ -0,0 +1,897 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// 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 "libGLESv2/mathutil.h" + +#include "libEGL/main.h" + +// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros +#define REF_RAST 0 + +// The "Debug This Pixel..." feature in PIX often fails when using the +// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7 +// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file. +#if !defined(ANGLE_ENABLE_D3D9EX) +// Enables use of the IDirect3D9Ex interface, when available +#define ANGLE_ENABLE_D3D9EX 1 +#endif // !defined(ANGLE_ENABLE_D3D9EX) + +namespace egl +{ +Display::Display(HDC deviceContext) : mDc(deviceContext) +{ + mD3d9Module = NULL; + + mD3d9 = NULL; + mD3d9Ex = NULL; + mDevice = NULL; + mDeviceEx = NULL; + mDeviceWindow = NULL; + + mAdapter = D3DADAPTER_DEFAULT; + + #if REF_RAST == 1 || defined(FORCE_REF_RAST) + mDeviceType = D3DDEVTYPE_REF; + #else + mDeviceType = D3DDEVTYPE_HAL; + #endif + + mMinSwapInterval = 1; + mMaxSwapInterval = 1; +} + +Display::~Display() +{ + terminate(); +} + +bool Display::initialize() +{ + if (isInitialized()) + { + return true; + } + + mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); + if (mD3d9Module == NULL) + { + terminate(); + return false; + } + + typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); + Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); + + // Use Direct3D9Ex if available. Among other things, this version is less + // inclined to report a lost context, for example when the user switches + // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. + if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) + { + ASSERT(mD3d9Ex); + mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9)); + ASSERT(mD3d9); + } + else + { + mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); + } + + if (mD3d9) + { + if (mDc != NULL) + { + // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to + } + + HRESULT result; + + // Give up on getting device caps after about one second. + for (int i = 0; i < 10; ++i) + { + result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); + + if (SUCCEEDED(result)) + { + break; + } + else if (result == D3DERR_NOTAVAILABLE) + { + Sleep(100); // Give the driver some time to initialize/recover + } + else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from + { + terminate(); + return error(EGL_BAD_ALLOC, false); + } + } + + if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0)) + { + terminate(); + return error(EGL_NOT_INITIALIZED, false); + } + + // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported. + // This is required by Texture2D::convertToRenderTarget. + if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0) + { + terminate(); + return error(EGL_NOT_INITIALIZED, false); + } + + mMinSwapInterval = 4; + mMaxSwapInterval = 0; + + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) {mMinSwapInterval = std::min(mMinSwapInterval, 0); mMaxSwapInterval = std::max(mMaxSwapInterval, 0);} + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) {mMinSwapInterval = std::min(mMinSwapInterval, 1); mMaxSwapInterval = std::max(mMaxSwapInterval, 1);} + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) {mMinSwapInterval = std::min(mMinSwapInterval, 2); mMaxSwapInterval = std::max(mMaxSwapInterval, 2);} + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) {mMinSwapInterval = std::min(mMinSwapInterval, 3); mMaxSwapInterval = std::max(mMaxSwapInterval, 3);} + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) {mMinSwapInterval = std::min(mMinSwapInterval, 4); mMaxSwapInterval = std::max(mMaxSwapInterval, 4);} + + mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); + + const D3DFORMAT renderTargetFormats[] = + { + D3DFMT_A1R5G5B5, + // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value. + D3DFMT_A8R8G8B8, + D3DFMT_R5G6B5, + // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format + D3DFMT_X8R8G8B8 + }; + + const D3DFORMAT depthStencilFormats[] = + { + D3DFMT_UNKNOWN, + // D3DFMT_D16_LOCKABLE, + D3DFMT_D32, + // D3DFMT_D15S1, + D3DFMT_D24S8, + D3DFMT_D24X8, + // D3DFMT_D24X4S4, + D3DFMT_D16, + // D3DFMT_D32F_LOCKABLE, + // D3DFMT_D24FS8 + }; + + D3DDISPLAYMODE currentDisplayMode; + mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); + + ConfigSet configSet; + + for (int formatIndex = 0; formatIndex < sizeof(renderTargetFormats) / sizeof(D3DFORMAT); formatIndex++) + { + D3DFORMAT renderTargetFormat = renderTargetFormats[formatIndex]; + + HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat); + + if (SUCCEEDED(result)) + { + for (int depthStencilIndex = 0; depthStencilIndex < sizeof(depthStencilFormats) / sizeof(D3DFORMAT); depthStencilIndex++) + { + D3DFORMAT depthStencilFormat = depthStencilFormats[depthStencilIndex]; + HRESULT result = D3D_OK; + + if(depthStencilFormat != D3DFMT_UNKNOWN) + { + result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat); + } + + if (SUCCEEDED(result)) + { + if(depthStencilFormat != D3DFMT_UNKNOWN) + { + result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat); + } + + if (SUCCEEDED(result)) + { + // FIXME: enumerate multi-sampling + + configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0, + mDeviceCaps.MaxTextureWidth, mDeviceCaps.MaxTextureHeight); + } + } + } + } + } + + // Give the sorted configs a unique ID and store them internally + EGLint index = 1; + for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++) + { + Config configuration = *config; + configuration.mConfigID = index; + index++; + + mConfigSet.mSet.insert(configuration); + } + } + + if (!isInitialized()) + { + terminate(); + + return false; + } + + initExtensionString(); + + static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); + static const TCHAR className[] = TEXT("STATIC"); + + mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); + + return true; +} + +void Display::terminate() +{ + while (!mSurfaceSet.empty()) + { + destroySurface(*mSurfaceSet.begin()); + } + + while (!mContextSet.empty()) + { + destroyContext(*mContextSet.begin()); + } + + if (mDevice) + { + // If the device is lost, reset it first to prevent leaving the driver in an unstable state + if (isDeviceLost()) + { + resetDevice(); + } + + mDevice->Release(); + mDevice = NULL; + } + + if (mDeviceEx) + { + mDeviceEx->Release(); + mDeviceEx = NULL; + } + + if (mD3d9) + { + mD3d9->Release(); + mD3d9 = NULL; + } + + if (mDeviceWindow) + { + DestroyWindow(mDeviceWindow); + mDeviceWindow = NULL; + } + + if (mD3d9Ex) + { + mD3d9Ex->Release(); + mD3d9Ex = NULL; + } + + if (mD3d9Module) + { + mD3d9Module = NULL; + } +} + +void Display::startScene() +{ + if (!mSceneStarted) + { + long result = mDevice->BeginScene(); + 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; + case EGL_MAX_PBUFFER_WIDTH: *value = configuration->mMaxPBufferWidth; break; + case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->mMaxPBufferHeight; break; + case EGL_MAX_PBUFFER_PIXELS: *value = configuration->mMaxPBufferPixels; break; + default: + return false; + } + + return true; +} + +bool Display::createDevice() +{ + D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); + DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES; + + HRESULT result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); + + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) + { + return error(EGL_BAD_ALLOC, false); + } + + if (FAILED(result)) + { + result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST); + return error(EGL_BAD_ALLOC, false); + } + } + + if (mD3d9Ex) + { + result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx); + ASSERT(SUCCEEDED(result)); + } + + // Permanent non-default states + mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); + + mSceneStarted = false; + + return true; +} + +bool Display::resetDevice() +{ + D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); + HRESULT result; + + do + { + Sleep(0); // Give the graphics driver some CPU time + + result = mDevice->Reset(&presentParameters); + } + while (result == D3DERR_DEVICELOST); + + if (FAILED(result)) + { + return error(EGL_BAD_ALLOC, false); + } + + ASSERT(SUCCEEDED(result)); + + return true; +} + +EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList) +{ + const Config *configuration = mConfigSet.get(config); + + if (attribList) + { + while (*attribList != EGL_NONE) + { + switch (attribList[0]) + { + case EGL_RENDER_BUFFER: + switch (attribList[1]) + { + case EGL_BACK_BUFFER: + break; + case EGL_SINGLE_BUFFER: + return error(EGL_BAD_MATCH, EGL_NO_SURFACE); // Rendering directly to front buffer not supported + default: + return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + } + break; + case EGL_VG_COLORSPACE: + return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + case EGL_VG_ALPHA_FORMAT: + return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + default: + return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + } + + attribList += 2; + } + } + + if (hasExistingWindowSurface(window)) + { + return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + } + + Surface *surface = new Surface(this, configuration, window); + + if (!surface->initialize()) + { + delete surface; + return EGL_NO_SURFACE; + } + + mSurfaceSet.insert(surface); + + return success(surface); +} + +EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList) +{ + EGLint width = 0, height = 0; + EGLenum textureFormat = EGL_NO_TEXTURE; + EGLenum textureTarget = EGL_NO_TEXTURE; + const Config *configuration = mConfigSet.get(config); + + if (attribList) + { + while (*attribList != EGL_NONE) + { + switch (attribList[0]) + { + case EGL_WIDTH: + width = attribList[1]; + break; + case EGL_HEIGHT: + height = attribList[1]; + break; + case EGL_LARGEST_PBUFFER: + if (attribList[1] != EGL_FALSE) + UNIMPLEMENTED(); // FIXME + break; + case EGL_TEXTURE_FORMAT: + switch (attribList[1]) + { + case EGL_NO_TEXTURE: + case EGL_TEXTURE_RGB: + case EGL_TEXTURE_RGBA: + textureFormat = attribList[1]; + break; + default: + return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + } + break; + case EGL_TEXTURE_TARGET: + switch (attribList[1]) + { + case EGL_NO_TEXTURE: + case EGL_TEXTURE_2D: + textureTarget = attribList[1]; + break; + default: + return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + } + break; + case EGL_MIPMAP_TEXTURE: + if (attribList[1] != EGL_FALSE) + return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + break; + case EGL_VG_COLORSPACE: + return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + case EGL_VG_ALPHA_FORMAT: + return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + default: + return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + } + + attribList += 2; + } + } + + if (width < 0 || height < 0) + { + return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + } + + if (width == 0 || height == 0) + { + return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + } + + if (textureFormat != EGL_NO_TEXTURE && !getNonPower2TextureSupport() && (!gl::isPow2(width) || !gl::isPow2(height))) + { + return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + } + + if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) || + (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE)) + { + return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + } + + if (!(configuration->mSurfaceType & EGL_PBUFFER_BIT)) + { + return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + } + + if ((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) || + (textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE)) + { + return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + } + + Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget); + + if (!surface->initialize()) + { + delete surface; + return EGL_NO_SURFACE; + } + + mSurfaceSet.insert(surface); + + return success(surface); +} + +EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext) +{ + if (!mDevice) + { + if (!createDevice()) + { + return NULL; + } + } + else if (isDeviceLost()) // Lost device + { + // Release surface resources to make the Reset() succeed + for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) + { + (*surface)->release(); + } + + if (!resetDevice()) + { + return NULL; + } + + // Restore any surfaces that may have been lost + for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) + { + (*surface)->resetSwapChain(); + } + } + + 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() const +{ + return mD3d9 != NULL && mConfigSet.size() > 0; +} + +bool Display::isValidConfig(EGLConfig config) +{ + return mConfigSet.get(config) != NULL; +} + +bool Display::isValidContext(gl::Context *context) +{ + return mContextSet.find(context) != mContextSet.end(); +} + +bool Display::isValidSurface(egl::Surface *surface) +{ + return mSurfaceSet.find(surface) != mSurfaceSet.end(); +} + +bool Display::hasExistingWindowSurface(HWND window) +{ + for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) + { + if ((*surface)->getWindowHandle() == window) + { + return true; + } + } + + return false; +} + +EGLint Display::getMinSwapInterval() +{ + return mMinSwapInterval; +} + +EGLint Display::getMaxSwapInterval() +{ + return mMaxSwapInterval; +} + +IDirect3DDevice9 *Display::getDevice() +{ + if (!mDevice) + { + if (!createDevice()) + { + return NULL; + } + } + + return mDevice; +} + +D3DCAPS9 Display::getDeviceCaps() +{ + return mDeviceCaps; +} + +D3DADAPTER_IDENTIFIER9 *Display::getAdapterIdentifier() +{ + return &mAdapterIdentifier; +} + +bool Display::isDeviceLost() +{ + if (mDeviceEx) + { + return FAILED(mDeviceEx->CheckDeviceState(NULL)); + } + else + { + return FAILED(mDevice->TestCooperativeLevel()); + } +} + +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, ¤tDisplayMode); + + return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1)); +} + +bool Display::getFloatTextureSupport(bool *filtering, bool *renderable) +{ + D3DDISPLAYMODE currentDisplayMode; + mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); + + *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, + D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, + D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); + + *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, + D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F))&& + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, + D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); + + if (!filtering && !renderable) + { + return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, + D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, + D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); + } + else + { + return true; + } +} + +bool Display::getHalfFloatTextureSupport(bool *filtering, bool *renderable) +{ + D3DDISPLAYMODE currentDisplayMode; + mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); + + *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, + D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, + D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); + + *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, + D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, + D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); + + if (!filtering && !renderable) + { + return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, + D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, + D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); + } + else + { + return true; + } +} + +bool Display::getLuminanceTextureSupport() +{ + D3DDISPLAYMODE currentDisplayMode; + mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); + + return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8)); +} + +bool Display::getLuminanceAlphaTextureSupport() +{ + D3DDISPLAYMODE currentDisplayMode; + mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); + + return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8)); +} + +D3DPOOL Display::getBufferPool(DWORD usage) const +{ + if (mD3d9Ex != NULL) + { + return D3DPOOL_DEFAULT; + } + else + { + if (!(usage & D3DUSAGE_DYNAMIC)) + { + return D3DPOOL_MANAGED; + } + } + + return D3DPOOL_DEFAULT; +} + +bool Display::getEventQuerySupport() +{ + IDirect3DQuery9 *query; + HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query); + if (SUCCEEDED(result)) + { + query->Release(); + } + + return result != D3DERR_NOTAVAILABLE; +} + +D3DPRESENT_PARAMETERS Display::getDefaultPresentParameters() +{ + D3DPRESENT_PARAMETERS presentParameters = {0}; + + // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters. + presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN; + presentParameters.BackBufferCount = 1; + presentParameters.BackBufferFormat = D3DFMT_UNKNOWN; + presentParameters.BackBufferWidth = 1; + presentParameters.BackBufferHeight = 1; + presentParameters.EnableAutoDepthStencil = FALSE; + presentParameters.Flags = 0; + presentParameters.hDeviceWindow = mDeviceWindow; + presentParameters.MultiSampleQuality = 0; + presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; + presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + presentParameters.Windowed = TRUE; + + return presentParameters; +} + +void Display::initExtensionString() +{ + mExtensionString += "EGL_ANGLE_query_surface_pointer "; + + if (isD3d9ExDevice()) { + mExtensionString += "EGL_ANGLE_surface_d3d_texture_2d_share_handle "; + mExtensionString += "EGL_ANGLE_d3d_share_handle_client_buffer "; + } + + std::string::size_type end = mExtensionString.find_last_not_of(' '); + if (end != std::string::npos) + { + mExtensionString.resize(end+1); + } +} + +const char *Display::getExtensionString() const +{ + return mExtensionString.c_str(); +} + +// Only Direct3D 10 ready devices support all the necessary vertex texture formats. +// We test this using D3D9 by checking support for the R16F format. +bool Display::getVertexTextureSupport() const +{ + if (!isInitialized() || mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(3, 0)) + { + return false; + } + + D3DDISPLAYMODE currentDisplayMode; + mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); + + HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F); + + return SUCCEEDED(result); +} + +bool Display::getNonPower2TextureSupport() const +{ + return !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && + !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && + !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL); +} + +} diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Display.h b/Source/ThirdParty/ANGLE/src/libEGL/Display.h new file mode 100644 index 000000000..86de5cd4b --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libEGL/Display.h @@ -0,0 +1,118 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// 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); + + EGLSurface createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList); + EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList); + EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext); + + void destroySurface(egl::Surface *surface); + void destroyContext(gl::Context *context); + + bool isInitialized() const; + bool isValidConfig(EGLConfig config); + bool isValidContext(gl::Context *context); + bool isValidSurface(egl::Surface *surface); + bool hasExistingWindowSurface(HWND window); + + EGLint getMinSwapInterval(); + EGLint getMaxSwapInterval(); + + virtual IDirect3DDevice9 *getDevice(); + virtual D3DCAPS9 getDeviceCaps(); + virtual D3DADAPTER_IDENTIFIER9 *getAdapterIdentifier(); + bool isDeviceLost(); + virtual void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray); + virtual bool getCompressedTextureSupport(); + virtual bool getEventQuerySupport(); + virtual bool getFloatTextureSupport(bool *filtering, bool *renderable); + virtual bool getHalfFloatTextureSupport(bool *filtering, bool *renderable); + virtual bool getLuminanceTextureSupport(); + virtual bool getLuminanceAlphaTextureSupport(); + virtual bool getVertexTextureSupport() const; + virtual bool getNonPower2TextureSupport() const; + virtual D3DPOOL getBufferPool(DWORD usage) const; + + bool isD3d9ExDevice() { return mD3d9Ex != NULL; } + const char *getExtensionString() const; + + private: + DISALLOW_COPY_AND_ASSIGN(Display); + + D3DPRESENT_PARAMETERS getDefaultPresentParameters(); + + const HDC mDc; + + HMODULE mD3d9Module; + + UINT mAdapter; + D3DDEVTYPE mDeviceType; + IDirect3D9 *mD3d9; // Always valid after successful initialization. + IDirect3D9Ex *mD3d9Ex; // Might be null if D3D9Ex is not supported. + IDirect3DDevice9 *mDevice; + IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported. + D3DCAPS9 mDeviceCaps; + D3DADAPTER_IDENTIFIER9 mAdapterIdentifier; + HWND mDeviceWindow; + + bool mSceneStarted; + EGLint mMaxSwapInterval; + EGLint mMinSwapInterval; + + typedef std::set<Surface*> SurfaceSet; + SurfaceSet mSurfaceSet; + + ConfigSet mConfigSet; + + typedef std::set<gl::Context*> ContextSet; + ContextSet mContextSet; + + bool createDevice(); + bool resetDevice(); + + void initExtensionString(); + std::string mExtensionString; +}; +} + +#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 000000000..eafe5e2d3 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp @@ -0,0 +1,495 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Surface.cpp: Implements the egl::Surface class, representing a drawing surface +// such as the client area of a window, including any back buffers. +// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3. + +#include <tchar.h> + +#include "libEGL/Surface.h" + +#include "common/debug.h" +#include "libGLESv2/Texture.h" + +#include "libEGL/main.h" +#include "libEGL/Display.h" + +#include <dwmapi.h> + +namespace egl +{ + +namespace +{ +const int versionWindowsVista = MAKEWORD(0x00, 0x06); +const int versionWindows7 = MAKEWORD(0x01, 0x06); + +// Return the version of the operating system in a format suitable for ordering +// comparison. +int getComparableOSVersion() +{ + DWORD version = GetVersion(); + int majorVersion = LOBYTE(LOWORD(version)); + int minorVersion = HIBYTE(LOWORD(version)); + return MAKEWORD(minorVersion, majorVersion); +} +} + +Surface::Surface(Display *display, const Config *config, HWND window) + : mDisplay(display), mConfig(config), mWindow(window) +{ + mSwapChain = NULL; + mDepthStencil = NULL; + mRenderTarget = NULL; + mOffscreenTexture = NULL; + mShareHandle = NULL; + mTexture = NULL; + mTextureFormat = EGL_NO_TEXTURE; + mTextureTarget = EGL_NO_TEXTURE; + + mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio + mRenderBuffer = EGL_BACK_BUFFER; + mSwapBehavior = EGL_BUFFER_PRESERVED; + mSwapInterval = -1; + setSwapInterval(1); + + subclassWindow(); +} + +Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType) + : mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height) +{ + mSwapChain = NULL; + mDepthStencil = NULL; + mRenderTarget = NULL; + mOffscreenTexture = NULL; + mWindowSubclassed = false; + mTexture = NULL; + mTextureFormat = textureFormat; + mTextureTarget = textureType; + + mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio + mRenderBuffer = EGL_BACK_BUFFER; + mSwapBehavior = EGL_BUFFER_PRESERVED; + mSwapInterval = -1; + setSwapInterval(1); +} + +Surface::~Surface() +{ + unsubclassWindow(); + release(); +} + +bool Surface::initialize() +{ + ASSERT(!mSwapChain && !mOffscreenTexture && !mDepthStencil); + + if (!resetSwapChain()) + return false; + + // Modify present parameters for this window, if we are composited, + // to minimize the amount of queuing done by DWM between our calls to + // present and the actual screen. + if (mWindow && (getComparableOSVersion() >= versionWindowsVista)) { + BOOL isComposited; + HRESULT result = DwmIsCompositionEnabled(&isComposited); + if (SUCCEEDED(result) && isComposited) { + DWM_PRESENT_PARAMETERS presentParams; + memset(&presentParams, 0, sizeof(presentParams)); + presentParams.cbSize = sizeof(DWM_PRESENT_PARAMETERS); + presentParams.cBuffer = 2; + + result = DwmSetPresentParameters(mWindow, &presentParams); + if (FAILED(result)) + ERR("Unable to set present parameters: %081X", result); + } + } + + return true; +} + +void Surface::release() +{ + if (mSwapChain) + { + mSwapChain->Release(); + mSwapChain = NULL; + } + + if (mDepthStencil) + { + mDepthStencil->Release(); + mDepthStencil = NULL; + } + + if (mRenderTarget) + { + mRenderTarget->Release(); + mRenderTarget = NULL; + } + + if (mOffscreenTexture) + { + mOffscreenTexture->Release(); + mOffscreenTexture = NULL; + } + + if (mTexture) + { + mTexture->releaseTexImage(); + mTexture = NULL; + } +} + +bool Surface::resetSwapChain() +{ + if (!mWindow) + { + return resetSwapChain(mWidth, mHeight); + } + + RECT windowRect; + if (!GetClientRect(getWindowHandle(), &windowRect)) + { + ASSERT(false); + + ERR("Could not retrieve the window dimensions"); + return false; + } + + return resetSwapChain(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top); +} + +bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) +{ + IDirect3DDevice9 *device = mDisplay->getDevice(); + + if (device == NULL) + { + return false; + } + + // Evict all non-render target textures to system memory and release all resources + // before reallocating them to free up as much video memory as possible. + device->EvictManagedResources(); + release(); + + D3DPRESENT_PARAMETERS presentParameters = {0}; + HRESULT result; + + bool useFlipEx = (getComparableOSVersion() >= versionWindows7) && mDisplay->isD3d9ExDevice(); + + // FlipEx causes unseemly stretching when resizing windows AND when one + // draws outside of the WM_PAINT callback. While this is seldom a problem in + // single process applications, it is particuarly noticeable in multiprocess + // applications. Therefore, if the creator process of our window is not in + // the current process, disable use of FlipEx. + DWORD windowPID; + GetWindowThreadProcessId(mWindow, &windowPID); + if(windowPID != GetCurrentProcessId()) + useFlipEx = false; + + presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat; + // We set BackBufferCount = 1 even when we use D3DSWAPEFFECT_FLIPEX. + // We do this because DirectX docs are a bit vague whether to set this to 1 + // or 2. The runtime seems to accept 1, so we speculate that either it is + // forcing it to 2 without telling us, or better, doing something smart + // behind the scenes knowing that we don't need more. + presentParameters.BackBufferCount = 1; + presentParameters.BackBufferFormat = mConfig->mRenderTargetFormat; + presentParameters.EnableAutoDepthStencil = FALSE; + presentParameters.Flags = 0; + presentParameters.hDeviceWindow = getWindowHandle(); + presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented + presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented + presentParameters.PresentationInterval = mPresentInterval; + // Use flipEx on Win7 or greater. + if(useFlipEx) + presentParameters.SwapEffect = D3DSWAPEFFECT_FLIPEX; + else + presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + presentParameters.Windowed = TRUE; + presentParameters.BackBufferWidth = backbufferWidth; + presentParameters.BackBufferHeight = backbufferHeight; + + if (mWindow) + { + result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain); + } else { + HANDLE *pShareHandle = NULL; + if (mDisplay->isD3d9ExDevice()) { + pShareHandle = &mShareHandle; + } + + result = device->CreateTexture(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET, + presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle); + } + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + + ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); + release(); + return error(EGL_BAD_ALLOC, false); + } + + if (mConfig->mDepthStencilFormat != D3DFMT_UNKNOWN) + { + result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, + presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType, + presentParameters.MultiSampleQuality, FALSE, &mDepthStencil, NULL); + } + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + + ERR("Could not create depthstencil surface for new swap chain: %08lX", result); + release(); + return error(EGL_BAD_ALLOC, false); + } + + if (mWindow) { + mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mRenderTarget); + InvalidateRect(mWindow, NULL, FALSE); + } else { + mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget); + } + + mWidth = presentParameters.BackBufferWidth; + mHeight = presentParameters.BackBufferHeight; + + mPresentIntervalDirty = false; + return true; +} + +HWND Surface::getWindowHandle() +{ + return mWindow; +} + + +#define kSurfaceProperty _TEXT("Egl::SurfaceOwner") +#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc") + +static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) +{ + if (message == WM_SIZE) + { + Surface* surf = reinterpret_cast<Surface*>(GetProp(hwnd, kSurfaceProperty)); + if(surf) + { + surf->checkForOutOfDateSwapChain(); + } + } + WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc)); + return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam); +} + +void Surface::subclassWindow() +{ + if (!mWindow) + { + return; + } + + DWORD processId; + DWORD threadId = GetWindowThreadProcessId(mWindow, &processId); + if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId()) + { + return; + } + + SetLastError(0); + LONG oldWndProc = SetWindowLong(mWindow, GWL_WNDPROC, reinterpret_cast<LONG>(SurfaceWindowProc)); + if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS) + { + mWindowSubclassed = false; + return; + } + + SetProp(mWindow, kSurfaceProperty, reinterpret_cast<HANDLE>(this)); + SetProp(mWindow, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc)); + mWindowSubclassed = true; +} + +void Surface::unsubclassWindow() +{ + if(!mWindowSubclassed) + { + return; + } + + // un-subclass + LONG parentWndFunc = reinterpret_cast<LONG>(GetProp(mWindow, kParentWndProc)); + + // Check the windowproc is still SurfaceWindowProc. + // If this assert fails, then it is likely the application has subclassed the + // hwnd as well and did not unsubclass before destroying its EGL context. The + // application should be modified to either subclass before initializing the + // EGL context, or to unsubclass before destroying the EGL context. + if(parentWndFunc) + { + LONG prevWndFunc = SetWindowLong(mWindow, GWL_WNDPROC, parentWndFunc); + ASSERT(prevWndFunc == reinterpret_cast<LONG>(SurfaceWindowProc)); + } + + RemoveProp(mWindow, kSurfaceProperty); + RemoveProp(mWindow, kParentWndProc); + mWindowSubclassed = false; +} + +bool Surface::checkForOutOfDateSwapChain() +{ + RECT client; + if (!GetClientRect(getWindowHandle(), &client)) + { + ASSERT(false); + return false; + } + + // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information. + int clientWidth = client.right - client.left; + int clientHeight = client.bottom - client.top; + bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); + + if (sizeDirty || mPresentIntervalDirty) + { + resetSwapChain(clientWidth, clientHeight); + if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this) + { + glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this); + } + + return true; + } + return false; +} + +DWORD Surface::convertInterval(EGLint interval) +{ + switch(interval) + { + case 0: return D3DPRESENT_INTERVAL_IMMEDIATE; + case 1: return D3DPRESENT_INTERVAL_ONE; + case 2: return D3DPRESENT_INTERVAL_TWO; + case 3: return D3DPRESENT_INTERVAL_THREE; + case 4: return D3DPRESENT_INTERVAL_FOUR; + default: UNREACHABLE(); + } + + return D3DPRESENT_INTERVAL_DEFAULT; +} + +bool Surface::swap() +{ + if (mSwapChain) + { + mDisplay->endScene(); + + HRESULT result = mSwapChain->Present(NULL, NULL, NULL, NULL, 0); + + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) + { + return error(EGL_BAD_ALLOC, false); + } + + if (result == D3DERR_DEVICELOST || result == D3DERR_DEVICEHUNG || result == D3DERR_DEVICEREMOVED) + { + return error(EGL_CONTEXT_LOST, false); + } + + ASSERT(SUCCEEDED(result)); + + checkForOutOfDateSwapChain(); + } + + 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; +} + +IDirect3DTexture9 *Surface::getOffscreenTexture() +{ + if (mOffscreenTexture) + { + mOffscreenTexture->AddRef(); + } + + return mOffscreenTexture; +} + +void Surface::setSwapInterval(EGLint interval) +{ + if (mSwapInterval == interval) + { + return; + } + + mSwapInterval = interval; + mSwapInterval = std::max(mSwapInterval, mDisplay->getMinSwapInterval()); + mSwapInterval = std::min(mSwapInterval, mDisplay->getMaxSwapInterval()); + + mPresentInterval = convertInterval(mSwapInterval); + mPresentIntervalDirty = true; +} + +EGLenum Surface::getTextureFormat() const +{ + return mTextureFormat; +} + +EGLenum Surface::getTextureTarget() const +{ + return mTextureTarget; +} + +void Surface::setBoundTexture(gl::Texture2D *texture) +{ + mTexture = texture; +} + +gl::Texture2D *Surface::getBoundTexture() const +{ + return mTexture; +} + +D3DFORMAT Surface::getFormat() const +{ + return mConfig->mRenderTargetFormat; +} +} diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Surface.h b/Source/ThirdParty/ANGLE/src/libEGL/Surface.h new file mode 100644 index 000000000..99c4b6769 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libEGL/Surface.h @@ -0,0 +1,105 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Surface.h: Defines the egl::Surface class, representing a drawing surface +// such as the client area of a window, including any back buffers. +// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3. + +#ifndef INCLUDE_SURFACE_H_ +#define INCLUDE_SURFACE_H_ + +#define EGLAPI +#include <EGL/egl.h> +#include <d3d9.h> + +#include "common/angleutils.h" + +namespace gl +{ +class Texture2D; +} + +namespace egl +{ +class Display; +class Config; + +class Surface +{ + public: + Surface(Display *display, const egl::Config *config, HWND window); + Surface(Display *display, const egl::Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget); + + ~Surface(); + + bool initialize(); + void release(); + bool resetSwapChain(); + + HWND getWindowHandle(); + bool swap(); + + virtual EGLint getWidth() const; + virtual EGLint getHeight() const; + + virtual IDirect3DSurface9 *getRenderTarget(); + virtual IDirect3DSurface9 *getDepthStencil(); + virtual IDirect3DTexture9 *getOffscreenTexture(); + + HANDLE getShareHandle() { return mShareHandle; } + + void setSwapInterval(EGLint interval); + bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update + + virtual EGLenum getTextureFormat() const; + virtual EGLenum getTextureTarget() const; + virtual D3DFORMAT getFormat() const; + + virtual void setBoundTexture(gl::Texture2D *texture); + virtual gl::Texture2D *getBoundTexture() const; + +private: + DISALLOW_COPY_AND_ASSIGN(Surface); + + Display *const mDisplay; + IDirect3DSwapChain9 *mSwapChain; + IDirect3DSurface9 *mDepthStencil; + IDirect3DSurface9* mRenderTarget; + IDirect3DTexture9* mOffscreenTexture; + + HANDLE mShareHandle; + + void subclassWindow(); + void unsubclassWindow(); + bool resetSwapChain(int backbufferWidth, int backbufferHeight); + static DWORD convertInterval(EGLint interval); + + const HWND mWindow; // Window that the surface is created for. + bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking + const egl::Config *mConfig; // EGL config surface was created with + EGLint mHeight; // Height of surface + EGLint mWidth; // Width of surface +// EGLint horizontalResolution; // Horizontal dot pitch +// EGLint verticalResolution; // Vertical dot pitch +// EGLBoolean largestPBuffer; // If true, create largest pbuffer possible +// EGLBoolean mipmapTexture; // True if texture has mipmaps +// EGLint mipmapLevel; // Mipmap level to render to +// EGLenum multisampleResolve; // Multisample resolve behavior + EGLint mPixelAspectRatio; // Display aspect ratio + EGLenum mRenderBuffer; // Render buffer + EGLenum mSwapBehavior; // Buffer swap behavior + EGLenum mTextureFormat; // Format of texture: RGB, RGBA, or no texture + EGLenum mTextureTarget; // Type of texture: 2D or no texture +// EGLenum vgAlphaFormat; // Alpha format for OpenVG +// EGLenum vgColorSpace; // Color space for OpenVG + EGLint mSwapInterval; + DWORD mPresentInterval; + bool mPresentIntervalDirty; + gl::Texture2D *mTexture; +}; +} + +#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 000000000..8689a4ecc --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libEGL/libEGL.cpp @@ -0,0 +1,1170 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// libEGL.cpp: Implements the exported EGL functions. + +#include <exception> + +#include "common/debug.h" +#include "common/version.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/Texture.h" + +#include "libEGL/main.h" +#include "libEGL/Display.h" + + +bool validateDisplay(egl::Display *display) +{ + if (display == EGL_NO_DISPLAY) + { + return error(EGL_BAD_DISPLAY, false); + } + + if (!display->isInitialized()) + { + return error(EGL_NOT_INITIALIZED, false); + } + + return true; +} + +bool validateConfig(egl::Display *display, EGLConfig config) +{ + if (!validateDisplay(display)) + { + return false; + } + + if (!display->isValidConfig(config)) + { + return error(EGL_BAD_CONFIG, false); + } + + return true; +} + +bool validateContext(egl::Display *display, gl::Context *context) +{ + if (!validateDisplay(display)) + { + return false; + } + + if (!display->isValidContext(context)) + { + return error(EGL_BAD_CONTEXT, false); + } + + return true; +} + +bool validateSurface(egl::Display *display, egl::Surface *surface) +{ + if (!validateDisplay(display)) + { + return false; + } + + if (!display->isValidSurface(surface)) + { + return error(EGL_BAD_SURFACE, false); + } + + return true; +} + +extern "C" +{ +EGLint __stdcall eglGetError(void) +{ + EVENT("()"); + + EGLint error = egl::getCurrentError(); + + if (error != EGL_SUCCESS) + { + egl::setCurrentError(EGL_SUCCESS); + } + + return error; +} + +EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id) +{ + EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id); + + try + { + // 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) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)", + dpy, major, minor); + + try + { + if (dpy == EGL_NO_DISPLAY) + { + return error(EGL_BAD_DISPLAY, EGL_FALSE); + } + + egl::Display *display = static_cast<egl::Display*>(dpy); + + if (!display->initialize()) + { + return error(EGL_NOT_INITIALIZED, EGL_FALSE); + } + + if (major) *major = 1; + if (minor) *minor = 4; + + return success(EGL_TRUE); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_FALSE); + } + + return EGL_FALSE; +} + +EGLBoolean __stdcall eglTerminate(EGLDisplay dpy) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy); + + try + { + if (dpy == EGL_NO_DISPLAY) + { + return error(EGL_BAD_DISPLAY, EGL_FALSE); + } + + egl::Display *display = static_cast<egl::Display*>(dpy); + + display->terminate(); + + return success(EGL_TRUE); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_FALSE); + } + + return EGL_FALSE; +} + +const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + + if (!validateDisplay(display)) + { + return NULL; + } + + switch (name) + { + case EGL_CLIENT_APIS: + return success("OpenGL_ES"); + case EGL_EXTENSIONS: + return display->getExtensionString(); + case EGL_VENDOR: + return success("Google Inc."); + case EGL_VERSION: + return success("1.4 (ANGLE "VERSION_STRING")"); + } + + return error(EGL_BAD_PARAMETER, (const char*)NULL); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, (const char*)NULL); + } + + return NULL; +} + +EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, " + "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", + dpy, configs, config_size, num_config); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + + if (!validateDisplay(display)) + { + return EGL_FALSE; + } + + if (!num_config) + { + return error(EGL_BAD_PARAMETER, EGL_FALSE); + } + + const EGLint attribList[] = {EGL_NONE}; + + if (!display->getConfigs(configs, attribList, config_size, num_config)) + { + return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + } + + return success(EGL_TRUE); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_FALSE); + } + + return EGL_FALSE; +} + +EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, " + "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", + dpy, attrib_list, configs, config_size, num_config); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + + if (!validateDisplay(display)) + { + return EGL_FALSE; + } + + if (!num_config) + { + return error(EGL_BAD_PARAMETER, EGL_FALSE); + } + + const EGLint attribList[] = {EGL_NONE}; + + if (!attrib_list) + { + attrib_list = attribList; + } + + display->getConfigs(configs, attrib_list, config_size, num_config); + + return success(EGL_TRUE); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_FALSE); + } + + return EGL_FALSE; +} + +EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", + dpy, config, attribute, value); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + + if (!validateConfig(display, config)) + { + return EGL_FALSE; + } + + if (!display->getConfigAttrib(config, attribute, value)) + { + return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + } + + return success(EGL_TRUE); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_FALSE); + } + + return EGL_FALSE; +} + +EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, " + "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + + if (!validateConfig(display, config)) + { + return EGL_NO_SURFACE; + } + + HWND window = (HWND)win; + + if (!IsWindow(window)) + { + return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + } + + return display->createWindowSurface(window, config, attrib_list); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + } + + return EGL_NO_SURFACE; +} + +EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", + dpy, config, attrib_list); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + + if (!validateConfig(display, config)) + { + return EGL_NO_SURFACE; + } + + return display->createOffscreenSurface(config, NULL, attrib_list); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + } + + return EGL_NO_SURFACE; +} + +EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, " + "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + + if (!validateConfig(display, config)) + { + return EGL_NO_SURFACE; + } + + UNIMPLEMENTED(); // FIXME + + return success(EGL_NO_SURFACE); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + } + + return EGL_NO_SURFACE; +} + +EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); + + if (!validateSurface(display, eglSurface)) + { + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE) + { + return error(EGL_BAD_SURFACE, EGL_FALSE); + } + + display->destroySurface((egl::Surface*)surface); + + return success(EGL_TRUE); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_FALSE); + } + + return EGL_FALSE; +} + +EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", + dpy, surface, attribute, value); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + egl::Surface *eglSurface = (egl::Surface*)surface; + + if (!validateSurface(display, eglSurface)) + { + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE) + { + return error(EGL_BAD_SURFACE, EGL_FALSE); + } + + switch (attribute) + { + case EGL_VG_ALPHA_FORMAT: + UNIMPLEMENTED(); // FIXME + break; + case EGL_VG_COLORSPACE: + UNIMPLEMENTED(); // FIXME + break; + case EGL_CONFIG_ID: + UNIMPLEMENTED(); // FIXME + break; + case EGL_HEIGHT: + *value = eglSurface->getHeight(); + break; + case EGL_HORIZONTAL_RESOLUTION: + UNIMPLEMENTED(); // FIXME + break; + case EGL_LARGEST_PBUFFER: + UNIMPLEMENTED(); // FIXME + break; + case EGL_MIPMAP_TEXTURE: + UNIMPLEMENTED(); // FIXME + break; + case EGL_MIPMAP_LEVEL: + UNIMPLEMENTED(); // FIXME + break; + case EGL_MULTISAMPLE_RESOLVE: + UNIMPLEMENTED(); // FIXME + break; + case EGL_PIXEL_ASPECT_RATIO: + UNIMPLEMENTED(); // FIXME + break; + case EGL_RENDER_BUFFER: + UNIMPLEMENTED(); // FIXME + break; + case EGL_SWAP_BEHAVIOR: + UNIMPLEMENTED(); // FIXME + break; + case EGL_TEXTURE_FORMAT: + UNIMPLEMENTED(); // FIXME + break; + case EGL_TEXTURE_TARGET: + UNIMPLEMENTED(); // FIXME + break; + case EGL_VERTICAL_RESOLUTION: + UNIMPLEMENTED(); // FIXME + break; + case EGL_WIDTH: + *value = eglSurface->getWidth(); + break; + 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 eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value) +{ + TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)", + dpy, surface, attribute, value); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + egl::Surface *eglSurface = (egl::Surface*)surface; + + if (!validateSurface(display, eglSurface)) + { + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE) + { + return error(EGL_BAD_SURFACE, EGL_FALSE); + } + + switch (attribute) + { + case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: + *value = (void*) eglSurface->getShareHandle(); + break; + default: + return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + } + + return success(EGL_TRUE); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_FALSE); + } + + return EGL_FALSE; +} + +EGLBoolean __stdcall eglBindAPI(EGLenum api) +{ + EVENT("(EGLenum api = 0x%X)", api); + + try + { + switch (api) + { + case EGL_OPENGL_API: + case EGL_OPENVG_API: + return error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation + case EGL_OPENGL_ES_API: + break; + default: + return error(EGL_BAD_PARAMETER, EGL_FALSE); + } + + egl::setCurrentAPI(api); + + return success(EGL_TRUE); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_FALSE); + } + + return EGL_FALSE; +} + +EGLenum __stdcall eglQueryAPI(void) +{ + EVENT("()"); + + try + { + EGLenum API = egl::getCurrentAPI(); + + return success(API); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_FALSE); + } + + return EGL_FALSE; +} + +EGLBoolean __stdcall eglWaitClient(void) +{ + EVENT("()"); + + try + { + UNIMPLEMENTED(); // FIXME + + return success(0); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_FALSE); + } + + return EGL_FALSE; +} + +EGLBoolean __stdcall eglReleaseThread(void) +{ + EVENT("()"); + + try + { + eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); + + return success(EGL_TRUE); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_FALSE); + } + + return EGL_FALSE; +} + +EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, " + "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", + dpy, buftype, buffer, config, attrib_list); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + + if (!validateConfig(display, config)) + { + return EGL_NO_SURFACE; + } + + if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer) + { + return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + } + + return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + } + + return EGL_NO_SURFACE; +} + +EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)", + dpy, surface, attribute, value); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); + + if (!validateSurface(display, eglSurface)) + { + return EGL_FALSE; + } + + UNIMPLEMENTED(); // FIXME + + return success(EGL_TRUE); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_FALSE); + } + + return EGL_FALSE; +} + +EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); + + if (!validateSurface(display, eglSurface)) + { + return EGL_FALSE; + } + + if (buffer != EGL_BACK_BUFFER) + { + return error(EGL_BAD_PARAMETER, EGL_FALSE); + } + + if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) + { + return error(EGL_BAD_SURFACE, EGL_FALSE); + } + + if (eglSurface->getBoundTexture()) + { + return error(EGL_BAD_ACCESS, EGL_FALSE); + } + + if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) + { + return error(EGL_BAD_MATCH, EGL_FALSE); + } + + glBindTexImage(eglSurface); + + 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) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); + + if (!validateSurface(display, eglSurface)) + { + return EGL_FALSE; + } + + if (buffer != EGL_BACK_BUFFER) + { + return error(EGL_BAD_PARAMETER, EGL_FALSE); + } + + if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) + { + return error(EGL_BAD_SURFACE, EGL_FALSE); + } + + if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) + { + return error(EGL_BAD_MATCH, EGL_FALSE); + } + + gl::Texture2D *texture = eglSurface->getBoundTexture(); + + if (texture) + { + texture->releaseTexImage(); + } + + return success(EGL_TRUE); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_FALSE); + } + + return EGL_FALSE; +} + +EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + + if (!validateDisplay(display)) + { + return EGL_FALSE; + } + + egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface()); + + if (draw_surface == NULL) + { + return error(EGL_BAD_SURFACE, EGL_FALSE); + } + + draw_surface->setSwapInterval(interval); + + return success(EGL_TRUE); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_FALSE); + } + + return EGL_FALSE; +} + +EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, " + "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list); + + try + { + // Get the requested client version (default is 1) and check it is two. + EGLint client_version = 1; + if (attrib_list) + { + for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2) + { + if (attribute[0] == EGL_CONTEXT_CLIENT_VERSION) + { + client_version = attribute[1]; + } + else + { + return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + } + } + } + + if (client_version != 2) + { + return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); + } + + egl::Display *display = static_cast<egl::Display*>(dpy); + + if (!validateConfig(display, config)) + { + return EGL_NO_CONTEXT; + } + + EGLContext context = display->createContext(config, static_cast<gl::Context*>(share_context)); + + return success(context); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT); + } + + return EGL_NO_CONTEXT; +} + +EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + gl::Context *context = static_cast<gl::Context*>(ctx); + + if (!validateContext(display, context)) + { + return EGL_FALSE; + } + + if (ctx == EGL_NO_CONTEXT) + { + return error(EGL_BAD_CONTEXT, EGL_FALSE); + } + + display->destroyContext(context); + + return success(EGL_TRUE); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_FALSE); + } + + return EGL_FALSE; +} + +EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)", + dpy, draw, read, ctx); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + gl::Context *context = static_cast<gl::Context*>(ctx); + IDirect3DDevice9 *device = display->getDevice(); + + if (!device || display->isDeviceLost()) + { + return error(EGL_CONTEXT_LOST, EGL_FALSE); + } + + if (ctx != EGL_NO_CONTEXT && !validateContext(display, context)) + { + return EGL_FALSE; + } + + if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(draw))) || + (read != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(read)))) + { + return EGL_FALSE; + } + + if (draw != read) + { + UNIMPLEMENTED(); // FIXME + } + + egl::Surface* previousDraw = static_cast<egl::Surface*>(egl::getCurrentDrawSurface()); + egl::Surface* previousRead = static_cast<egl::Surface*>(egl::getCurrentReadSurface()); + + egl::setCurrentDisplay(dpy); + egl::setCurrentDrawSurface(draw); + egl::setCurrentReadSurface(read); + + 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) +{ + EVENT("()"); + + 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) +{ + EVENT("(EGLint readdraw = %d)", readdraw); + + try + { + if (readdraw == EGL_READ) + { + EGLSurface read = egl::getCurrentReadSurface(); + return success(read); + } + else if (readdraw == EGL_DRAW) + { + EGLSurface draw = egl::getCurrentDrawSurface(); + return success(draw); + } + else + { + return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + } + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + } + + return EGL_NO_SURFACE; +} + +EGLDisplay __stdcall eglGetCurrentDisplay(void) +{ + EVENT("()"); + + try + { + EGLDisplay dpy = egl::getCurrentDisplay(); + + return success(dpy); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_NO_DISPLAY); + } + + return EGL_NO_DISPLAY; +} + +EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", + dpy, ctx, attribute, value); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + gl::Context *context = static_cast<gl::Context*>(ctx); + + if (!validateContext(display, context)) + { + return EGL_FALSE; + } + + UNIMPLEMENTED(); // FIXME + + return success(0); + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_FALSE); + } + + return EGL_FALSE; +} + +EGLBoolean __stdcall eglWaitGL(void) +{ + EVENT("()"); + + 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) +{ + EVENT("(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) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + egl::Surface *eglSurface = (egl::Surface*)surface; + + if (!validateSurface(display, eglSurface)) + { + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE) + { + return error(EGL_BAD_SURFACE, EGL_FALSE); + } + + if (eglSurface->swap()) + { + return success(EGL_TRUE); + } + } + catch(std::bad_alloc&) + { + return error(EGL_BAD_ALLOC, EGL_FALSE); + } + + return EGL_FALSE; +} + +EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target); + + try + { + egl::Display *display = static_cast<egl::Display*>(dpy); + egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); + + if (!validateSurface(display, eglSurface)) + { + return EGL_FALSE; + } + + 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) +{ + EVENT("(const char *procname = \"%s\")", procname); + + try + { + struct Extension + { + const char *name; + __eglMustCastToProperFunctionPointerType address; + }; + + static const Extension eglExtensions[] = + { + {"eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE}, + {"", 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 000000000..71a5e6797 --- /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.rc b/Source/ThirdParty/ANGLE/src/libEGL/libEGL.rc new file mode 100644 index 000000000..15ed28562 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libEGL/libEGL.rc @@ -0,0 +1,102 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" +#include "../common/version.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "#include ""../common/version.h""\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION + PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "ANGLE libEGL Dynamic Link Library" + VALUE "FileVersion", VERSION_STRING + VALUE "InternalName", "libEGL" + VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc." + VALUE "OriginalFilename", "libEGL.dll" + VALUE "PrivateBuild", VERSION_STRING + VALUE "ProductName", "ANGLE libEGL Dynamic Link Library" + VALUE "ProductVersion", VERSION_STRING + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/Source/ThirdParty/ANGLE/src/libEGL/libEGL.vcproj b/Source/ThirdParty/ANGLE/src/libEGL/libEGL.vcproj new file mode 100644 index 000000000..676bc988b --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libEGL/libEGL.vcproj @@ -0,0 +1,266 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="9.00" + Name="libEGL" + ProjectGUID="{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}" + RootNamespace="libEGL" + Keyword="Win32Proj" + TargetFrameworkVersion="131072" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="$(SolutionDir)$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="2" + CharacterSet="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="$(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="d3d9.lib dxguid.lib dwmapi.lib" + LinkIncremental="2" + ModuleDefinitionFile="libEGL.def" + DelayLoadDLLs="dwmapi.dll" + 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
mkdir "$(ProjectDir)..\..\lib\$(ConfigurationName)\"
copy "$(OutDir)\libEGL.dll" "$(ProjectDir)..\..\lib\$(ConfigurationName)\"
copy "$(OutDir)\libEGL.lib" "$(ProjectDir)..\..\lib\$(ConfigurationName)\"
@echo off
" + /> + </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="d3d9.lib dxguid.lib dwmapi.lib" + LinkIncremental="1" + ModuleDefinitionFile="libEGL.def" + DelayLoadDLLs="dwmapi.lib" + 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
mkdir "$(ProjectDir)..\..\lib\$(ConfigurationName)\"
copy "$(OutDir)\libEGL.dll" "$(ProjectDir)..\..\lib\$(ConfigurationName)\"
copy "$(OutDir)\libEGL.lib" "$(ProjectDir)..\..\lib\$(ConfigurationName)\"
@echo off
" + /> + </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=".\resource.h" + > + </File> + <File + RelativePath=".\Surface.h" + > + </File> + <File + RelativePath="..\common\version.h" + > + </File> + </Filter> + <File + RelativePath=".\libEGL.def" + > + </File> + <File + RelativePath=".\libEGL.rc" + > + </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 000000000..1c107bf56 --- /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: + { +#if !defined(ANGLE_DISABLE_TRACE) + FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt"); + + if (debug) + { + fclose(debug); + debug = fopen(TRACE_OUTPUT_FILE, "wt"); // Erase + fclose(debug); + } +#endif + + currentTLS = 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 000000000..d09d9e6bc --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libEGL/main.h @@ -0,0 +1,61 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// main.h: Management of thread-local data. + +#ifndef LIBEGL_MAIN_H_ +#define LIBEGL_MAIN_H_ + +#define EGLAPI +#include <EGL/egl.h> +#include <EGL/eglext.h> + +namespace egl +{ +struct Current +{ + EGLint error; + EGLenum API; + EGLDisplay display; + EGLSurface drawSurface; + EGLSurface readSurface; +}; + +void setCurrentError(EGLint error); +EGLint getCurrentError(); + +void setCurrentAPI(EGLenum API); +EGLenum getCurrentAPI(); + +void setCurrentDisplay(EGLDisplay dpy); +EGLDisplay getCurrentDisplay(); + +void setCurrentDrawSurface(EGLSurface surface); +EGLSurface getCurrentDrawSurface(); + +void setCurrentReadSurface(EGLSurface surface); +EGLSurface getCurrentReadSurface(); +} + +void error(EGLint errorCode); + +template<class T> +const T &error(EGLint errorCode, const T &returnValue) +{ + error(errorCode); + + return returnValue; +} + +template<class T> +const T &success(const T &returnValue) +{ + egl::setCurrentError(EGL_SUCCESS); + + return returnValue; +} + +#endif // LIBEGL_MAIN_H_ diff --git a/Source/ThirdParty/ANGLE/src/libEGL/resource.h b/Source/ThirdParty/ANGLE/src/libEGL/resource.h new file mode 100644 index 000000000..3921f4c07 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libEGL/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by libEGL.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.cpp new file mode 100644 index 000000000..923a9de07 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.cpp @@ -0,0 +1,599 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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 result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return error(GL_OUT_OF_MEMORY); + } + + void *lockPtr = NULL; + result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0); + + if (FAILED(result) || lockPtr == NULL) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return error(GL_OUT_OF_MEMORY); + } + + memcpy(lockPtr, quad, sizeof(quad)); + mQuadVertexBuffer->Unlock(); + + static const D3DVERTEXELEMENT9 elements[] = + { + { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, + D3DDECL_END() + }; + + result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return error(GL_OUT_OF_MEMORY); + } +} + +template <class D3DShaderType> +bool Blit::setShader(ShaderId source, const char *profile, + 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::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) +{ + IDirect3DDevice9 *device = getDevice(); + + D3DSURFACE_DESC sourceDesc; + D3DSURFACE_DESC destDesc; + source->GetDesc(&sourceDesc); + dest->GetDesc(&destDesc); + + if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET) // Can use StretchRect + { + RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)}; + HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return error(GL_OUT_OF_MEMORY, false); + } + } + else + { + return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest); + } + + return true; +} + +bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) +{ + IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect); + if (!texture) + { + return false; + } + + IDirect3DDevice9 *device = getDevice(); + + saveState(); + + device->SetTexture(0, texture); + device->SetRenderTarget(0, dest); + + setViewport(sourceRect, xoffset, yoffset); + + setCommonBlitState(); + if (setFormatConvertShaders(destFormat)) + { + render(); + } + + texture->Release(); + + restoreState(); + + return true; +} + +bool Blit::setFormatConvertShaders(GLenum destFormat) +{ + bool okay = setVertexShader(SHADER_VS_STANDARD); + + switch (destFormat) + { + default: UNREACHABLE(); + case GL_RGBA: + case GL_BGRA_EXT: + case GL_RGB: + case GL_ALPHA: + okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK); + break; + + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + okay = okay && setPixelShader(SHADER_PS_LUMINANCE); + break; + } + + if (!okay) + { + return false; + } + + enum { X = 0, Y = 1, Z = 2, W = 3 }; + + // The meaning of this constant depends on the shader that was selected. + // See the shader assembly code above for details. + float psConst0[4] = { 0, 0, 0, 0 }; + + switch (destFormat) + { + default: UNREACHABLE(); + case GL_RGBA: + case GL_BGRA_EXT: + psConst0[X] = 1; + psConst0[Z] = 1; + break; + + case GL_RGB: + psConst0[X] = 1; + psConst0[W] = 1; + break; + + case GL_ALPHA: + psConst0[Z] = 1; + break; + + case GL_LUMINANCE: + psConst0[Y] = 1; + break; + + case GL_LUMINANCE_ALPHA: + psConst0[X] = 1; + break; + } + + getDevice()->SetPixelShaderConstantF(0, psConst0, 1); + + return true; +} + +IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect) +{ + if (!surface) + { + return NULL; + } + + egl::Display *display = getDisplay(); + IDirect3DDevice9 *device = getDevice(); + + D3DSURFACE_DESC sourceDesc; + surface->GetDesc(&sourceDesc); + + // Copy the render target into a texture + IDirect3DTexture9 *texture; + HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); + } + + IDirect3DSurface9 *textureSurface; + result = texture->GetSurfaceLevel(0, &textureSurface); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + texture->Release(); + return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); + } + + display->endScene(); + result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE); + + textureSurface->Release(); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + texture->Release(); + return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); + } + + return texture; +} + +void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset) +{ + IDirect3DDevice9 *device = getDevice(); + + D3DVIEWPORT9 vp; + vp.X = xoffset; + vp.Y = yoffset; + vp.Width = sourceRect.right - sourceRect.left; + vp.Height = sourceRect.bottom - sourceRect.top; + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + device->SetViewport(&vp); + + float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 }; + device->SetVertexShaderConstantF(0, halfPixelAdjust, 1); +} + +void Blit::setCommonBlitState() +{ + IDirect3DDevice9 *device = getDevice(); + + device->SetDepthStencilSurface(NULL); + + device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); + device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); + device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); + + device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE); + device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + + RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle + device->SetScissorRect(&scissorRect); +} + +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 000000000..8928ecd07 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.h @@ -0,0 +1,94 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// 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) + bool copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); + + // Copy from source surface to dest surface. + // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) + // source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0. + bool formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); + + // 2x2 box filter sample from source to dest. + // Requires that source is RGB(A) and dest has the same format as source. + bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); + + private: + Context *mContext; + + IDirect3DVertexBuffer9 *mQuadVertexBuffer; + IDirect3DVertexDeclaration9 *mQuadVertexDeclaration; + + void initGeometry(); + + bool setFormatConvertShaders(GLenum destFormat); + + IDirect3DTexture9 *copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect); + void setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset); + void setCommonBlitState(); + RECT getSurfaceRect(IDirect3DSurface9 *surface) const; + + // This enum is used to index mCompiledShaders and mShaderSource. + enum ShaderId + { + SHADER_VS_STANDARD, + SHADER_VS_FLIPY, + SHADER_PS_PASSTHROUGH, + SHADER_PS_LUMINANCE, + SHADER_PS_COMPONENTMASK, + SHADER_COUNT + }; + + 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 000000000..2cd148e31 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.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. +// + +// Buffer.cpp: Implements the gl::Buffer class, representing storage of vertex and/or +// index data. Implements GL buffer objects and related functionality. +// [OpenGL ES 2.0.24] section 2.9 page 21. + +#include "libGLESv2/Buffer.h" + +#include "libGLESv2/main.h" +#include "libGLESv2/VertexDataManager.h" +#include "libGLESv2/IndexDataManager.h" + +namespace gl +{ + +Buffer::Buffer(GLuint id) : RefCountObject(id) +{ + mContents = NULL; + mSize = 0; + mUsage = GL_DYNAMIC_DRAW; + + mStaticVertexBuffer = NULL; + mStaticIndexBuffer = NULL; + mUnmodifiedDataUse = 0; +} + +Buffer::~Buffer() +{ + delete[] mContents; + delete mStaticVertexBuffer; + delete mStaticIndexBuffer; +} + +void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) +{ + if (size == 0) + { + delete[] mContents; + mContents = NULL; + } + else if (size != mSize) + { + delete[] mContents; + mContents = new GLubyte[size]; + memset(mContents, 0, size); + } + + if (data != NULL && size > 0) + { + memcpy(mContents, data, size); + } + + mSize = size; + mUsage = usage; + + invalidateStaticData(); + + if (usage == GL_STATIC_DRAW) + { + mStaticVertexBuffer = new StaticVertexBuffer(getDevice()); + mStaticIndexBuffer = new StaticIndexBuffer(getDevice()); + } +} + +void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) +{ + memcpy(mContents + offset, data, size); + + if ((mStaticVertexBuffer && mStaticVertexBuffer->size() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->size() != 0)) + { + invalidateStaticData(); + } +} + +StaticVertexBuffer *Buffer::getStaticVertexBuffer() +{ + return mStaticVertexBuffer; +} + +StaticIndexBuffer *Buffer::getStaticIndexBuffer() +{ + return mStaticIndexBuffer; +} + +void Buffer::invalidateStaticData() +{ + delete mStaticVertexBuffer; + mStaticVertexBuffer = NULL; + + delete mStaticIndexBuffer; + mStaticIndexBuffer = NULL; + + mUnmodifiedDataUse = 0; +} + +// Creates static buffers if sufficient used data has been left unmodified +void Buffer::promoteStaticUsage(int dataSize) +{ + if (!mStaticVertexBuffer && !mStaticIndexBuffer) + { + mUnmodifiedDataUse += dataSize; + + if (mUnmodifiedDataUse > 3 * mSize) + { + mStaticVertexBuffer = new StaticVertexBuffer(getDevice()); + mStaticIndexBuffer = new StaticIndexBuffer(getDevice()); + } + } +} + +} diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.h new file mode 100644 index 000000000..b6126267e --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.h @@ -0,0 +1,61 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// 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 StaticVertexBuffer; +class StaticIndexBuffer; + +class Buffer : public RefCountObject +{ + public: + explicit Buffer(GLuint id); + + virtual ~Buffer(); + + void bufferData(const void *data, GLsizeiptr size, GLenum usage); + void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset); + + void *data() { return mContents; } + size_t size() const { return mSize; } + GLenum usage() const { return mUsage; } + + StaticVertexBuffer *getStaticVertexBuffer(); + StaticIndexBuffer *getStaticIndexBuffer(); + void invalidateStaticData(); + void promoteStaticUsage(int dataSize); + + private: + DISALLOW_COPY_AND_ASSIGN(Buffer); + + GLubyte *mContents; + size_t mSize; + GLenum mUsage; + + StaticVertexBuffer *mStaticVertexBuffer; + StaticIndexBuffer *mStaticIndexBuffer; + size_t mUnmodifiedDataUse; +}; + +} + +#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 000000000..6c973ead2 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp @@ -0,0 +1,3766 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Context.cpp: Implements the gl::Context class, managing all GL state and performing +// rendering operations. It is the GLES2 specific implementation of EGLContext. + +#include "libGLESv2/Context.h" + +#include <algorithm> + +#include "libEGL/Display.h" + +#include "libGLESv2/main.h" +#include "libGLESv2/mathutil.h" +#include "libGLESv2/utilities.h" +#include "libGLESv2/Blit.h" +#include "libGLESv2/ResourceManager.h" +#include "libGLESv2/Buffer.h" +#include "libGLESv2/Fence.h" +#include "libGLESv2/FrameBuffer.h" +#include "libGLESv2/Program.h" +#include "libGLESv2/RenderBuffer.h" +#include "libGLESv2/Shader.h" +#include "libGLESv2/Texture.h" +#include "libGLESv2/VertexDataManager.h" +#include "libGLESv2/IndexDataManager.h" + +#undef near +#undef far + +namespace +{ + enum { CLOSING_INDEX_BUFFER_SIZE = 4096 }; +} + +namespace gl +{ +Context::Context(const egl::Config *config, const gl::Context *shareContext) : mConfig(config) +{ + mFenceHandleAllocator.setBaseHandle(0); + + setClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + mState.depthClearValue = 1.0f; + mState.stencilClearValue = 0; + + mState.cullFace = false; + mState.cullMode = GL_BACK; + mState.frontFace = GL_CCW; + mState.depthTest = false; + mState.depthFunc = GL_LESS; + mState.blend = false; + mState.sourceBlendRGB = GL_ONE; + mState.sourceBlendAlpha = GL_ONE; + mState.destBlendRGB = GL_ZERO; + mState.destBlendAlpha = GL_ZERO; + mState.blendEquationRGB = GL_FUNC_ADD; + mState.blendEquationAlpha = GL_FUNC_ADD; + mState.blendColor.red = 0; + mState.blendColor.green = 0; + mState.blendColor.blue = 0; + mState.blendColor.alpha = 0; + mState.stencilTest = false; + mState.stencilFunc = GL_ALWAYS; + mState.stencilRef = 0; + mState.stencilMask = -1; + mState.stencilWritemask = -1; + mState.stencilBackFunc = GL_ALWAYS; + mState.stencilBackRef = 0; + mState.stencilBackMask = - 1; + mState.stencilBackWritemask = -1; + mState.stencilFail = GL_KEEP; + mState.stencilPassDepthFail = GL_KEEP; + mState.stencilPassDepthPass = GL_KEEP; + mState.stencilBackFail = GL_KEEP; + mState.stencilBackPassDepthFail = GL_KEEP; + mState.stencilBackPassDepthPass = GL_KEEP; + mState.polygonOffsetFill = false; + mState.polygonOffsetFactor = 0.0f; + mState.polygonOffsetUnits = 0.0f; + mState.sampleAlphaToCoverage = false; + mState.sampleCoverage = false; + mState.sampleCoverageValue = 1.0f; + mState.sampleCoverageInvert = false; + mState.scissorTest = false; + mState.dither = true; + mState.generateMipmapHint = GL_DONT_CARE; + mState.fragmentShaderDerivativeHint = GL_DONT_CARE; + + mState.lineWidth = 1.0f; + + mState.viewportX = 0; + mState.viewportY = 0; + mState.viewportWidth = config->mDisplayMode.Width; + mState.viewportHeight = config->mDisplayMode.Height; + mState.zNear = 0.0f; + mState.zFar = 1.0f; + + mState.scissorX = 0; + mState.scissorY = 0; + mState.scissorWidth = config->mDisplayMode.Width; + mState.scissorHeight = config->mDisplayMode.Height; + + mState.colorMaskRed = true; + mState.colorMaskGreen = true; + mState.colorMaskBlue = true; + mState.colorMaskAlpha = true; + mState.depthMask = true; + + if (shareContext != NULL) + { + mResourceManager = shareContext->mResourceManager; + mResourceManager->addRef(); + } + else + { + mResourceManager = new ResourceManager(); + } + + // [OpenGL ES 2.0.24] section 3.7 page 83: + // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional + // and cube map texture state vectors respectively associated with them. + // In order that access to these initial textures not be lost, they are treated as texture + // objects all of whose names are 0. + + mTexture2DZero.set(new Texture2D(0)); + mTextureCubeMapZero.set(new TextureCubeMap(0)); + + mState.activeSampler = 0; + bindArrayBuffer(0); + bindElementArrayBuffer(0); + bindTextureCubeMap(0); + bindTexture2D(0); + bindReadFramebuffer(0); + bindDrawFramebuffer(0); + bindRenderbuffer(0); + + mState.currentProgram = 0; + + mState.packAlignment = 4; + mState.unpackAlignment = 4; + + mVertexDataManager = NULL; + mIndexDataManager = NULL; + mBlit = NULL; + mClosingIB = NULL; + + mInvalidEnum = false; + mInvalidValue = false; + mInvalidOperation = false; + mOutOfMemory = false; + mInvalidFramebufferOperation = false; + + mHasBeenCurrent = false; + + mSupportsCompressedTextures = false; + mSupportsEventQueries = 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 (!mFenceMap.empty()) + { + deleteFence(mFenceMap.begin()->first); + } + + while (!mMultiSampleSupport.empty()) + { + delete [] mMultiSampleSupport.begin()->second; + mMultiSampleSupport.erase(mMultiSampleSupport.begin()); + } + + for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) + { + for (int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; sampler++) + { + mState.samplerTexture[type][sampler].set(NULL); + } + } + + for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) + { + mIncompleteTextures[type].set(NULL); + } + + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + mState.vertexAttribute[i].mBoundBuffer.set(NULL); + } + + mState.arrayBuffer.set(NULL); + mState.elementArrayBuffer.set(NULL); + mState.renderbuffer.set(NULL); + + mTexture2DZero.set(NULL); + mTextureCubeMapZero.set(NULL); + + delete mVertexDataManager; + delete mIndexDataManager; + delete mBlit; + delete mClosingIB; + + if (mMaskedClearSavedState) + { + mMaskedClearSavedState->Release(); + } + + mResourceManager->release(); +} + +void Context::makeCurrent(egl::Display *display, egl::Surface *surface) +{ + IDirect3DDevice9 *device = display->getDevice(); + + if (!mHasBeenCurrent) + { + mDeviceCaps = display->getDeviceCaps(); + + mVertexDataManager = new VertexDataManager(this, device); + mIndexDataManager = new IndexDataManager(this, device); + mBlit = new Blit(this); + + mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0); + mSupportsVertexTexture = display->getVertexTextureSupport(); + mSupportsNonPower2Texture = display->getNonPower2TextureSupport(); + + mMaxTextureDimension = std::min(std::min((int)mDeviceCaps.MaxTextureWidth, (int)mDeviceCaps.MaxTextureHeight), + (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE); + mMaxCubeTextureDimension = std::min(mMaxTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE); + mMaxRenderbufferDimension = mMaxTextureDimension; + mMaxTextureLevel = log2(mMaxTextureDimension) + 1; + TRACE("MaxTextureDimension=%d, MaxCubeTextureDimension=%d, MaxRenderbufferDimension=%d, MaxTextureLevel=%d", + mMaxTextureDimension, mMaxCubeTextureDimension, mMaxRenderbufferDimension, mMaxTextureLevel); + + 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; + + mSupportsEventQueries = display->getEventQuerySupport(); + mSupportsCompressedTextures = display->getCompressedTextureSupport(); + mSupportsFloatTextures = display->getFloatTextureSupport(&mSupportsFloatLinearFilter, &mSupportsFloatRenderableTextures); + mSupportsHalfFloatTextures = display->getHalfFloatTextureSupport(&mSupportsHalfFloatLinearFilter, &mSupportsHalfFloatRenderableTextures); + mSupportsLuminanceTextures = display->getLuminanceTextureSupport(); + mSupportsLuminanceAlphaTextures = display->getLuminanceAlphaTextureSupport(); + + mSupports32bitIndices = mDeviceCaps.MaxVertexIndex >= (1 << 16); + + 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); + + if (defaultRenderTarget) + { + defaultRenderTarget->Release(); + } + + if (depthStencil) + { + depthStencil->Release(); + } + + markAllStateDirty(); +} + +// This function will set all of the state-related dirty flags, so that all state is set during next pre-draw. +void Context::markAllStateDirty() +{ + for (int t = 0; t < MAX_TEXTURE_IMAGE_UNITS; t++) + { + mAppliedTextureSerialPS[t] = 0; + } + + for (int t = 0; t < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; t++) + { + mAppliedTextureSerialVS[t] = 0; + } + + mAppliedProgramSerial = 0; + mAppliedRenderTargetSerial = 0; + mAppliedDepthbufferSerial = 0; + mAppliedStencilbufferSerial = 0; + mDepthStencilInitialized = false; + + mClearStateDirty = true; + mCullStateDirty = true; + mDepthStateDirty = true; + mMaskStateDirty = true; + mBlendStateDirty = true; + mStencilStateDirty = true; + mPolygonOffsetStateDirty = true; + mScissorStateDirty = true; + mSampleStateDirty = true; + mDitherStateDirty = true; + mFrontFaceDirty = true; +} + +void Context::setClearColor(float red, float green, float blue, float alpha) +{ + mState.colorClearValue.red = red; + mState.colorClearValue.green = green; + mState.colorClearValue.blue = blue; + mState.colorClearValue.alpha = alpha; +} + +void Context::setClearDepth(float depth) +{ + mState.depthClearValue = depth; +} + +void Context::setClearStencil(int stencil) +{ + mState.stencilClearValue = stencil; +} + +void Context::setCullFace(bool enabled) +{ + if (mState.cullFace != enabled) + { + mState.cullFace = enabled; + mCullStateDirty = true; + } +} + +bool Context::isCullFaceEnabled() const +{ + return mState.cullFace; +} + +void Context::setCullMode(GLenum mode) +{ + if (mState.cullMode != mode) + { + mState.cullMode = mode; + mCullStateDirty = true; + } +} + +void Context::setFrontFace(GLenum front) +{ + if (mState.frontFace != front) + { + mState.frontFace = front; + mFrontFaceDirty = true; + } +} + +void Context::setDepthTest(bool enabled) +{ + if (mState.depthTest != enabled) + { + mState.depthTest = enabled; + mDepthStateDirty = true; + } +} + +bool Context::isDepthTestEnabled() const +{ + return mState.depthTest; +} + +void Context::setDepthFunc(GLenum depthFunc) +{ + if (mState.depthFunc != depthFunc) + { + mState.depthFunc = depthFunc; + mDepthStateDirty = true; + } +} + +void Context::setDepthRange(float zNear, float zFar) +{ + mState.zNear = zNear; + mState.zFar = zFar; +} + +void Context::setBlend(bool enabled) +{ + if (mState.blend != enabled) + { + mState.blend = enabled; + mBlendStateDirty = true; + } +} + +bool Context::isBlendEnabled() const +{ + return mState.blend; +} + +void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha) +{ + if (mState.sourceBlendRGB != sourceRGB || + mState.sourceBlendAlpha != sourceAlpha || + mState.destBlendRGB != destRGB || + mState.destBlendAlpha != destAlpha) + { + mState.sourceBlendRGB = sourceRGB; + mState.destBlendRGB = destRGB; + mState.sourceBlendAlpha = sourceAlpha; + mState.destBlendAlpha = destAlpha; + mBlendStateDirty = true; + } +} + +void Context::setBlendColor(float red, float green, float blue, float alpha) +{ + if (mState.blendColor.red != red || + mState.blendColor.green != green || + mState.blendColor.blue != blue || + mState.blendColor.alpha != alpha) + { + mState.blendColor.red = red; + mState.blendColor.green = green; + mState.blendColor.blue = blue; + mState.blendColor.alpha = alpha; + mBlendStateDirty = true; + } +} + +void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation) +{ + if (mState.blendEquationRGB != rgbEquation || + mState.blendEquationAlpha != alphaEquation) + { + mState.blendEquationRGB = rgbEquation; + mState.blendEquationAlpha = alphaEquation; + mBlendStateDirty = true; + } +} + +void Context::setStencilTest(bool enabled) +{ + if (mState.stencilTest != enabled) + { + mState.stencilTest = enabled; + mStencilStateDirty = true; + } +} + +bool Context::isStencilTestEnabled() const +{ + return mState.stencilTest; +} + +void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask) +{ + if (mState.stencilFunc != stencilFunc || + mState.stencilRef != stencilRef || + mState.stencilMask != stencilMask) + { + mState.stencilFunc = stencilFunc; + mState.stencilRef = (stencilRef > 0) ? stencilRef : 0; + mState.stencilMask = stencilMask; + mStencilStateDirty = true; + } +} + +void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask) +{ + if (mState.stencilBackFunc != stencilBackFunc || + mState.stencilBackRef != stencilBackRef || + mState.stencilBackMask != stencilBackMask) + { + mState.stencilBackFunc = stencilBackFunc; + mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0; + mState.stencilBackMask = stencilBackMask; + mStencilStateDirty = true; + } +} + +void Context::setStencilWritemask(GLuint stencilWritemask) +{ + if (mState.stencilWritemask != stencilWritemask) + { + mState.stencilWritemask = stencilWritemask; + mStencilStateDirty = true; + } +} + +void Context::setStencilBackWritemask(GLuint stencilBackWritemask) +{ + if (mState.stencilBackWritemask != stencilBackWritemask) + { + mState.stencilBackWritemask = stencilBackWritemask; + mStencilStateDirty = true; + } +} + +void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass) +{ + if (mState.stencilFail != stencilFail || + mState.stencilPassDepthFail != stencilPassDepthFail || + mState.stencilPassDepthPass != stencilPassDepthPass) + { + mState.stencilFail = stencilFail; + mState.stencilPassDepthFail = stencilPassDepthFail; + mState.stencilPassDepthPass = stencilPassDepthPass; + mStencilStateDirty = true; + } +} + +void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass) +{ + if (mState.stencilBackFail != stencilBackFail || + mState.stencilBackPassDepthFail != stencilBackPassDepthFail || + mState.stencilBackPassDepthPass != stencilBackPassDepthPass) + { + mState.stencilBackFail = stencilBackFail; + mState.stencilBackPassDepthFail = stencilBackPassDepthFail; + mState.stencilBackPassDepthPass = stencilBackPassDepthPass; + mStencilStateDirty = true; + } +} + +void Context::setPolygonOffsetFill(bool enabled) +{ + if (mState.polygonOffsetFill != enabled) + { + mState.polygonOffsetFill = enabled; + mPolygonOffsetStateDirty = true; + } +} + +bool Context::isPolygonOffsetFillEnabled() const +{ + return mState.polygonOffsetFill; + +} + +void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units) +{ + if (mState.polygonOffsetFactor != factor || + mState.polygonOffsetUnits != units) + { + mState.polygonOffsetFactor = factor; + mState.polygonOffsetUnits = units; + mPolygonOffsetStateDirty = true; + } +} + +void Context::setSampleAlphaToCoverage(bool enabled) +{ + if (mState.sampleAlphaToCoverage != enabled) + { + mState.sampleAlphaToCoverage = enabled; + mSampleStateDirty = true; + } +} + +bool Context::isSampleAlphaToCoverageEnabled() const +{ + return mState.sampleAlphaToCoverage; +} + +void Context::setSampleCoverage(bool enabled) +{ + if (mState.sampleCoverage != enabled) + { + mState.sampleCoverage = enabled; + mSampleStateDirty = true; + } +} + +bool Context::isSampleCoverageEnabled() const +{ + return mState.sampleCoverage; +} + +void Context::setSampleCoverageParams(GLclampf value, bool invert) +{ + if (mState.sampleCoverageValue != value || + mState.sampleCoverageInvert != invert) + { + mState.sampleCoverageValue = value; + mState.sampleCoverageInvert = invert; + mSampleStateDirty = true; + } +} + +void Context::setScissorTest(bool enabled) +{ + if (mState.scissorTest != enabled) + { + mState.scissorTest = enabled; + mScissorStateDirty = true; + } +} + +bool Context::isScissorTestEnabled() const +{ + return mState.scissorTest; +} + +void Context::setDither(bool enabled) +{ + if (mState.dither != enabled) + { + mState.dither = enabled; + mDitherStateDirty = true; + } +} + +bool Context::isDitherEnabled() const +{ + return mState.dither; +} + +void Context::setLineWidth(GLfloat width) +{ + mState.lineWidth = width; +} + +void Context::setGenerateMipmapHint(GLenum hint) +{ + mState.generateMipmapHint = hint; +} + +void Context::setFragmentShaderDerivativeHint(GLenum hint) +{ + mState.fragmentShaderDerivativeHint = hint; + // TODO: Propagate the hint to shader translator so we can write + // ddx, ddx_coarse, or ddx_fine depending on the hint. + // Ignore for now. It is valid for implementations to ignore hint. +} + +void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) +{ + mState.viewportX = x; + mState.viewportY = y; + mState.viewportWidth = width; + mState.viewportHeight = height; +} + +void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height) +{ + if (mState.scissorX != x || mState.scissorY != y || + mState.scissorWidth != width || mState.scissorHeight != height) + { + mState.scissorX = x; + mState.scissorY = y; + mState.scissorWidth = width; + mState.scissorHeight = height; + mScissorStateDirty = true; + } +} + +void Context::setColorMask(bool red, bool green, bool blue, bool alpha) +{ + if (mState.colorMaskRed != red || mState.colorMaskGreen != green || + mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha) + { + mState.colorMaskRed = red; + mState.colorMaskGreen = green; + mState.colorMaskBlue = blue; + mState.colorMaskAlpha = alpha; + mMaskStateDirty = true; + } +} + +void Context::setDepthMask(bool mask) +{ + if (mState.depthMask != mask) + { + mState.depthMask = mask; + mMaskStateDirty = true; + } +} + +void Context::setActiveSampler(unsigned int active) +{ + mState.activeSampler = active; +} + +GLuint Context::getReadFramebufferHandle() const +{ + return mState.readFramebuffer; +} + +GLuint Context::getDrawFramebufferHandle() const +{ + return mState.drawFramebuffer; +} + +GLuint Context::getRenderbufferHandle() const +{ + return mState.renderbuffer.id(); +} + +GLuint Context::getArrayBufferHandle() const +{ + return mState.arrayBuffer.id(); +} + +void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) +{ + mState.vertexAttribute[attribNum].mArrayEnabled = enabled; +} + +const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum) +{ + return mState.vertexAttribute[attribNum]; +} + +void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized, + GLsizei stride, const void *pointer) +{ + mState.vertexAttribute[attribNum].mBoundBuffer.set(boundBuffer); + mState.vertexAttribute[attribNum].mSize = size; + mState.vertexAttribute[attribNum].mType = type; + mState.vertexAttribute[attribNum].mNormalized = normalized; + mState.vertexAttribute[attribNum].mStride = stride; + mState.vertexAttribute[attribNum].mPointer = pointer; +} + +const void *Context::getVertexAttribPointer(unsigned int attribNum) const +{ + return mState.vertexAttribute[attribNum].mPointer; +} + +const VertexAttributeArray &Context::getVertexAttributes() +{ + return mState.vertexAttribute; +} + +void Context::setPackAlignment(GLint alignment) +{ + mState.packAlignment = alignment; +} + +GLint Context::getPackAlignment() const +{ + return mState.packAlignment; +} + +void Context::setUnpackAlignment(GLint alignment) +{ + mState.unpackAlignment = alignment; +} + +GLint Context::getUnpackAlignment() const +{ + return mState.unpackAlignment; +} + +GLuint Context::createBuffer() +{ + return mResourceManager->createBuffer(); +} + +GLuint Context::createProgram() +{ + return mResourceManager->createProgram(); +} + +GLuint Context::createShader(GLenum type) +{ + return mResourceManager->createShader(type); +} + +GLuint Context::createTexture() +{ + return mResourceManager->createTexture(); +} + +GLuint Context::createRenderbuffer() +{ + return mResourceManager->createRenderbuffer(); +} + +// Returns an unused framebuffer name +GLuint Context::createFramebuffer() +{ + GLuint handle = mFramebufferHandleAllocator.allocate(); + + mFramebufferMap[handle] = NULL; + + return handle; +} + +GLuint Context::createFence() +{ + GLuint handle = mFenceHandleAllocator.allocate(); + + mFenceMap[handle] = new Fence; + + return handle; +} + +void Context::deleteBuffer(GLuint buffer) +{ + if (mResourceManager->getBuffer(buffer)) + { + detachBuffer(buffer); + } + + mResourceManager->deleteBuffer(buffer); +} + +void Context::deleteShader(GLuint shader) +{ + mResourceManager->deleteShader(shader); +} + +void Context::deleteProgram(GLuint program) +{ + mResourceManager->deleteProgram(program); +} + +void Context::deleteTexture(GLuint texture) +{ + if (mResourceManager->getTexture(texture)) + { + detachTexture(texture); + } + + mResourceManager->deleteTexture(texture); +} + +void Context::deleteRenderbuffer(GLuint renderbuffer) +{ + if (mResourceManager->getRenderbuffer(renderbuffer)) + { + detachRenderbuffer(renderbuffer); + } + + mResourceManager->deleteRenderbuffer(renderbuffer); +} + +void Context::deleteFramebuffer(GLuint framebuffer) +{ + FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer); + + if (framebufferObject != mFramebufferMap.end()) + { + detachFramebuffer(framebuffer); + + mFramebufferHandleAllocator.release(framebufferObject->first); + delete framebufferObject->second; + mFramebufferMap.erase(framebufferObject); + } +} + +void Context::deleteFence(GLuint fence) +{ + FenceMap::iterator fenceObject = mFenceMap.find(fence); + + if (fenceObject != mFenceMap.end()) + { + mFenceHandleAllocator.release(fenceObject->first); + delete fenceObject->second; + mFenceMap.erase(fenceObject); + } +} + +Buffer *Context::getBuffer(GLuint handle) +{ + return mResourceManager->getBuffer(handle); +} + +Shader *Context::getShader(GLuint handle) +{ + return mResourceManager->getShader(handle); +} + +Program *Context::getProgram(GLuint handle) +{ + return mResourceManager->getProgram(handle); +} + +Texture *Context::getTexture(GLuint handle) +{ + return mResourceManager->getTexture(handle); +} + +Renderbuffer *Context::getRenderbuffer(GLuint handle) +{ + return mResourceManager->getRenderbuffer(handle); +} + +Framebuffer *Context::getReadFramebuffer() +{ + return getFramebuffer(mState.readFramebuffer); +} + +Framebuffer *Context::getDrawFramebuffer() +{ + return getFramebuffer(mState.drawFramebuffer); +} + +void Context::bindArrayBuffer(unsigned int buffer) +{ + mResourceManager->checkBufferAllocation(buffer); + + mState.arrayBuffer.set(getBuffer(buffer)); +} + +void Context::bindElementArrayBuffer(unsigned int buffer) +{ + mResourceManager->checkBufferAllocation(buffer); + + mState.elementArrayBuffer.set(getBuffer(buffer)); +} + +void Context::bindTexture2D(GLuint texture) +{ + mResourceManager->checkTextureAllocation(texture, TEXTURE_2D); + + mState.samplerTexture[TEXTURE_2D][mState.activeSampler].set(getTexture(texture)); +} + +void Context::bindTextureCubeMap(GLuint texture) +{ + mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE); + + mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].set(getTexture(texture)); +} + +void Context::bindReadFramebuffer(GLuint framebuffer) +{ + if (!getFramebuffer(framebuffer)) + { + mFramebufferMap[framebuffer] = new Framebuffer(); + } + + mState.readFramebuffer = framebuffer; +} + +void Context::bindDrawFramebuffer(GLuint framebuffer) +{ + if (!getFramebuffer(framebuffer)) + { + mFramebufferMap[framebuffer] = new Framebuffer(); + } + + mState.drawFramebuffer = framebuffer; +} + +void Context::bindRenderbuffer(GLuint renderbuffer) +{ + mResourceManager->checkRenderbufferAllocation(renderbuffer); + + mState.renderbuffer.set(getRenderbuffer(renderbuffer)); +} + +void Context::useProgram(GLuint program) +{ + GLuint priorProgram = mState.currentProgram; + mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged. + + if (priorProgram != program) + { + Program *newProgram = mResourceManager->getProgram(program); + Program *oldProgram = mResourceManager->getProgram(priorProgram); + + if (newProgram) + { + newProgram->addRef(); + } + + if (oldProgram) + { + oldProgram->release(); + } + } +} + +void Context::setFramebufferZero(Framebuffer *buffer) +{ + delete mFramebufferMap[0]; + mFramebufferMap[0] = buffer; +} + +void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer) +{ + Renderbuffer *renderbufferObject = mState.renderbuffer.get(); + renderbufferObject->setStorage(renderbuffer); +} + +Framebuffer *Context::getFramebuffer(unsigned int handle) +{ + FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle); + + if (framebuffer == mFramebufferMap.end()) + { + return NULL; + } + else + { + return framebuffer->second; + } +} + +Fence *Context::getFence(unsigned int handle) +{ + FenceMap::iterator fence = mFenceMap.find(handle); + + if (fence == mFenceMap.end()) + { + return NULL; + } + else + { + return fence->second; + } +} + +Buffer *Context::getArrayBuffer() +{ + return mState.arrayBuffer.get(); +} + +Buffer *Context::getElementArrayBuffer() +{ + return mState.elementArrayBuffer.get(); +} + +Program *Context::getCurrentProgram() +{ + return mResourceManager->getProgram(mState.currentProgram); +} + +Texture2D *Context::getTexture2D() +{ + return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D)); +} + +TextureCubeMap *Context::getTextureCubeMap() +{ + return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE)); +} + +Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type) +{ + GLuint texid = mState.samplerTexture[type][sampler].id(); + + if (texid == 0) // Special case: 0 refers to different initial textures based on the target + { + switch (type) + { + default: UNREACHABLE(); + case TEXTURE_2D: return mTexture2DZero.get(); + case TEXTURE_CUBE: return mTextureCubeMapZero.get(); + } + } + + return mState.samplerTexture[type][sampler].get(); +} + +bool Context::getBooleanv(GLenum pname, GLboolean *params) +{ + switch (pname) + { + case GL_SHADER_COMPILER: *params = GL_TRUE; break; + case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break; + case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break; + case GL_COLOR_WRITEMASK: + params[0] = mState.colorMaskRed; + params[1] = mState.colorMaskGreen; + params[2] = mState.colorMaskBlue; + params[3] = mState.colorMaskAlpha; + break; + case GL_CULL_FACE: *params = mState.cullFace; break; + case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill; break; + case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage; break; + case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break; + case GL_SCISSOR_TEST: *params = mState.scissorTest; break; + case GL_STENCIL_TEST: *params = mState.stencilTest; break; + case GL_DEPTH_TEST: *params = mState.depthTest; break; + case GL_BLEND: *params = mState.blend; break; + case GL_DITHER: *params = mState.dither; break; + default: + return false; + } + + return true; +} + +bool Context::getFloatv(GLenum pname, GLfloat *params) +{ + // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation + // because it is stored as a float, despite the fact that the GL ES 2.0 spec names + // GetIntegerv as its native query function. As it would require conversion in any + // case, this should make no difference to the calling application. + switch (pname) + { + case GL_LINE_WIDTH: *params = mState.lineWidth; break; + case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break; + case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break; + case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break; + case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break; + case GL_ALIASED_LINE_WIDTH_RANGE: + params[0] = 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 = getMaximumVaryingVectors(); break; + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = getMaximumCombinedTextureImageUnits(); break; + case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = getMaximumVertexTextureImageUnits(); break; + case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break; + case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = getMaximumFragmentUniformVectors(); break; + case GL_MAX_RENDERBUFFER_SIZE: *params = getMaximumRenderbufferDimension(); break; + case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break; + case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break; + case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.id(); break; + case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer.id(); break; + //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE + case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mState.drawFramebuffer; break; + case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mState.readFramebuffer; break; + case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.id(); break; + case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break; + case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break; + case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break; + case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break; + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break; + case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break; + case GL_STENCIL_FUNC: *params = mState.stencilFunc; break; + case GL_STENCIL_REF: *params = mState.stencilRef; break; + case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break; + case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break; + case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break; + case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break; + case GL_STENCIL_FAIL: *params = mState.stencilFail; break; + case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break; + case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break; + case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break; + case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break; + case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break; + case GL_DEPTH_FUNC: *params = mState.depthFunc; break; + case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break; + case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break; + case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break; + case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break; + case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break; + case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break; + case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break; + case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break; + case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break; + case GL_SUBPIXEL_BITS: *params = 4; break; + case GL_MAX_TEXTURE_SIZE: *params = getMaximumTextureDimension(); break; + case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = getMaximumCubeTextureDimension(); break; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS: + { + 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(getMaximumRenderbufferDimension(), getMaximumTextureDimension()); + 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 > getMaximumCombinedTextureImageUnits() - 1) + { + error(GL_INVALID_OPERATION); + return false; + } + + *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].id(); + } + break; + case GL_TEXTURE_BINDING_CUBE_MAP: + { + if (mState.activeSampler < 0 || mState.activeSampler > getMaximumCombinedTextureImageUnits() - 1) + { + error(GL_INVALID_OPERATION); + return false; + } + + *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id(); + } + break; + 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_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: + case GL_RED_BITS: + case GL_GREEN_BITS: + case GL_BLUE_BITS: + case GL_ALPHA_BITS: + case GL_DEPTH_BITS: + case GL_STENCIL_BITS: + case GL_ELEMENT_ARRAY_BUFFER_BINDING: + case GL_CULL_FACE_MODE: + case GL_FRONT_FACE: + case GL_ACTIVE_TEXTURE: + case GL_STENCIL_FUNC: + case GL_STENCIL_VALUE_MASK: + case GL_STENCIL_REF: + case GL_STENCIL_FAIL: + case GL_STENCIL_PASS_DEPTH_FAIL: + case GL_STENCIL_PASS_DEPTH_PASS: + case GL_STENCIL_BACK_FUNC: + case GL_STENCIL_BACK_VALUE_MASK: + case GL_STENCIL_BACK_REF: + case GL_STENCIL_BACK_FAIL: + case GL_STENCIL_BACK_PASS_DEPTH_FAIL: + case GL_STENCIL_BACK_PASS_DEPTH_PASS: + case GL_DEPTH_FUNC: + case GL_BLEND_SRC_RGB: + case GL_BLEND_SRC_ALPHA: + case GL_BLEND_DST_RGB: + case GL_BLEND_DST_ALPHA: + case GL_BLEND_EQUATION_RGB: + case GL_BLEND_EQUATION_ALPHA: + case GL_STENCIL_WRITEMASK: + case GL_STENCIL_BACK_WRITEMASK: + case GL_STENCIL_CLEAR_VALUE: + case GL_SUBPIXEL_BITS: + case GL_MAX_TEXTURE_SIZE: + case GL_MAX_CUBE_MAP_TEXTURE_SIZE: + case GL_SAMPLE_BUFFERS: + case GL_SAMPLES: + case GL_IMPLEMENTATION_COLOR_READ_TYPE: + case GL_IMPLEMENTATION_COLOR_READ_FORMAT: + case GL_TEXTURE_BINDING_2D: + case GL_TEXTURE_BINDING_CUBE_MAP: + { + *type = GL_INT; + *numParams = 1; + } + break; + case GL_MAX_SAMPLES_ANGLE: + { + 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) + { + return error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + } + + IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget(); + + if (!renderTarget) + { + return false; // Context must be lost + } + + 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(); + if (!depthStencil) + { + ERR("Depth stencil pointer unexpectedly null."); + return false; + } + + depthbufferSerial = framebufferObject->getDepthbuffer()->getSerial(); + } + else if (framebufferObject->getStencilbufferType() != GL_NONE) + { + depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil(); + if (!depthStencil) + { + ERR("Depth stencil pointer unexpectedly null."); + return false; + } + + stencilbufferSerial = framebufferObject->getStencilbuffer()->getSerial(); + } + + if (depthbufferSerial != mAppliedDepthbufferSerial || + stencilbufferSerial != mAppliedStencilbufferSerial || + !mDepthStencilInitialized) + { + device->SetDepthStencilSurface(depthStencil); + mAppliedDepthbufferSerial = depthbufferSerial; + mAppliedStencilbufferSerial = stencilbufferSerial; + mDepthStencilInitialized = true; + } + + D3DVIEWPORT9 viewport; + D3DSURFACE_DESC desc; + renderTarget->GetDesc(&desc); + + float zNear = clamp01(mState.zNear); + float zFar = clamp01(mState.zFar); + + 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 + { + RECT rect = transformPixelRect(mState.viewportX, mState.viewportY, mState.viewportWidth, mState.viewportHeight, desc.Height); + viewport.X = clamp(rect.left, 0L, static_cast<LONG>(desc.Width)); + viewport.Y = clamp(rect.top, 0L, static_cast<LONG>(desc.Height)); + viewport.Width = clamp(rect.right - rect.left, 0L, static_cast<LONG>(desc.Width) - static_cast<LONG>(viewport.X)); + viewport.Height = clamp(rect.bottom - rect.top, 0L, static_cast<LONG>(desc.Height) - static_cast<LONG>(viewport.Y)); + viewport.MinZ = zNear; + viewport.MaxZ = zFar; + } + + if (viewport.Width <= 0 || viewport.Height <= 0) + { + return false; // Nothing to render + } + + device->SetViewport(&viewport); + + if (mScissorStateDirty) + { + if (mState.scissorTest) + { + RECT rect = transformPixelRect(mState.scissorX, mState.scissorY, mState.scissorWidth, mState.scissorHeight, desc.Height); + rect.left = clamp(rect.left, 0L, static_cast<LONG>(desc.Width)); + rect.top = clamp(rect.top, 0L, static_cast<LONG>(desc.Height)); + rect.right = clamp(rect.right, 0L, static_cast<LONG>(desc.Width)); + rect.bottom = clamp(rect.bottom, 0L, static_cast<LONG>(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, xy); + + GLint viewport = 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(viewport, 1, whxy); + + GLint depth = programObject->getDxDepthLocation(); + GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f}; + programObject->setUniform2fv(depth, 1, dz); + + GLint depthRange = programObject->getDxDepthRangeLocation(); + GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear}; + programObject->setUniform3fv(depthRange, 1, nearFarDiff); + } + + 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(); + + Framebuffer *framebufferObject = getDrawFramebuffer(); + + GLenum adjustedFrontFace = adjustWinding(mState.frontFace); + + GLint frontCCW = programObject->getDxFrontCCWLocation(); + GLint ccw = (adjustedFrontFace == GL_CCW); + programObject->setUniform1iv(frontCCW, 1, &ccw); + + GLint pointsOrLines = programObject->getDxPointsOrLinesLocation(); + GLint alwaysFront = !isTriangleMode(drawMode); + programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront); + + egl::Display *display = getDisplay(); + D3DADAPTER_IDENTIFIER9 *identifier = display->getAdapterIdentifier(); + bool zeroColorMaskAllowed = identifier->VendorId != 0x1002; + // Apparently some ATI cards have a bug where a draw with a zero color + // write mask can cause later draws to have incorrect results. Instead, + // set a nonzero color write mask but modify the blend state so that no + // drawing is done. + // http://code.google.com/p/angleproject/issues/detail?id=169 + + if (mCullStateDirty || mFrontFaceDirty) + { + if (mState.cullFace) + { + device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, adjustedFrontFace)); + } + else + { + device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + } + + mCullStateDirty = false; + } + + if (mDepthStateDirty) + { + if (mState.depthTest) + { + device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); + device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc)); + } + else + { + device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); + } + + mDepthStateDirty = false; + } + + if (!zeroColorMaskAllowed && (mMaskStateDirty || mBlendStateDirty)) + { + mBlendStateDirty = true; + mMaskStateDirty = true; + } + + 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(adjustedFrontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask); + device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, + es2dx::ConvertComparison(mState.stencilFunc)); + + device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil); + device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask); + + device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, + es2dx::ConvertStencilOp(mState.stencilFail)); + device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, + es2dx::ConvertStencilOp(mState.stencilPassDepthFail)); + device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, + es2dx::ConvertStencilOp(mState.stencilPassDepthPass)); + + device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask); + device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, + es2dx::ConvertComparison(mState.stencilBackFunc)); + + device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil); + device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask); + + device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, + es2dx::ConvertStencilOp(mState.stencilBackFail)); + device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, + es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail)); + device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, + es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass)); + } + else + { + device->SetRenderState(D3DRS_STENCILENABLE, FALSE); + } + + mStencilStateDirty = false; + mFrontFaceDirty = false; + } + + if (mMaskStateDirty) + { + int colorMask = es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, + mState.colorMaskBlue, mState.colorMaskAlpha); + if (colorMask == 0 && !zeroColorMaskAllowed) + { + // Enable green channel, but set blending so nothing will be drawn. + device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN); + device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + + device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); + device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + } + else + { + device->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask); + } + 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 (mSampleStateDirty) + { + if (mState.sampleAlphaToCoverage) + { + FIXME("Sample alpha to coverage is unimplemented."); + } + + device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); + if (mState.sampleCoverage) + { + unsigned int mask = 0; + if (mState.sampleCoverageValue != 0) + { + float threshold = 0.5f; + + for (int i = 0; i < framebufferObject->getSamples(); ++i) + { + mask <<= 1; + + if ((i + 1) * mState.sampleCoverageValue >= threshold) + { + threshold += 1.0f; + mask |= 1; + } + } + } + + if (mState.sampleCoverageInvert) + { + mask = ~mask; + } + + device->SetRenderState(D3DRS_MULTISAMPLEMASK, mask); + } + else + { + device->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); + } + + mSampleStateDirty = false; + } + + if (mDitherStateDirty) + { + device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE); + + mDitherStateDirty = false; + } +} + +GLenum Context::applyVertexBuffer(GLint first, GLsizei count) +{ + TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS]; + + GLenum err = mVertexDataManager->prepareVertexData(first, count, attributes); + if (err != GL_NO_ERROR) + { + return err; + } + + return mVertexDeclarationCache.applyDeclaration(attributes, getCurrentProgram()); +} + +// 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) +{ + IDirect3DDevice9 *device = getDevice(); + GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer.get(), indices, indexInfo); + + if (err == GL_NO_ERROR) + { + device->SetIndices(indexInfo->indexBuffer); + } + + 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() != mAppliedProgramSerial) + { + programObject->dirtyAllUniforms(); + mAppliedProgramSerial = programObject->getSerial(); + } + + programObject->applyUniforms(); +} + +// Applies the textures and sampler states to the Direct3D 9 device +void Context::applyTextures() +{ + applyTextures(SAMPLER_PIXEL); + + if (mSupportsVertexTexture) + { + applyTextures(SAMPLER_VERTEX); + } +} + +// For each Direct3D 9 sampler of either the pixel or vertex stage, +// looks up the corresponding OpenGL texture image unit and texture type, +// and sets the texture and its addressing/filtering state (or NULL when inactive). +void Context::applyTextures(SamplerType type) +{ + IDirect3DDevice9 *device = getDevice(); + Program *programObject = getCurrentProgram(); + + int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; // Range of Direct3D 9 samplers of given sampler type + + for (int samplerIndex = 0; samplerIndex < samplerCount; samplerIndex++) + { + int textureUnit = programObject->getSamplerMapping(type, samplerIndex); // OpenGL texture image unit index + int d3dSampler = (type == SAMPLER_PIXEL) ? samplerIndex : D3DVERTEXTEXTURESAMPLER0 + samplerIndex; + unsigned int *appliedTextureSerial = (type == SAMPLER_PIXEL) ? mAppliedTextureSerialPS : mAppliedTextureSerialVS; + + if (textureUnit != -1) + { + TextureType textureType = programObject->getSamplerTextureType(type, samplerIndex); + + Texture *texture = getSamplerTexture(textureUnit, textureType); + + if (appliedTextureSerial[samplerIndex] != texture->getSerial() || texture->isDirtyParameter() || texture->isDirtyImage()) + { + IDirect3DBaseTexture9 *d3dTexture = texture->getTexture(); + + if (d3dTexture) + { + if (appliedTextureSerial[samplerIndex] != texture->getSerial() || texture->isDirtyParameter()) + { + GLenum wrapS = texture->getWrapS(); + GLenum wrapT = texture->getWrapT(); + GLenum minFilter = texture->getMinFilter(); + GLenum magFilter = texture->getMagFilter(); + + device->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS)); + device->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT)); + + device->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter)); + D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter; + es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter); + device->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter); + device->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter); + } + + if (appliedTextureSerial[samplerIndex] != texture->getSerial() || texture->isDirtyImage()) + { + device->SetTexture(d3dSampler, d3dTexture); + } + } + else + { + device->SetTexture(d3dSampler, getIncompleteTexture(textureType)->getTexture()); + } + + appliedTextureSerial[samplerIndex] = texture->getSerial(); + texture->resetDirty(); + } + } + else + { + if (appliedTextureSerial[samplerIndex] != 0) + { + device->SetTexture(d3dSampler, NULL); + appliedTextureSerial[samplerIndex] = 0; + } + } + } +} + +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(); + + if (!renderTarget) + { + return; // Context must be lost, return silently + } + + 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 = transformPixelRect(x, y, width, height, desc.Height); + rect.left = clamp(rect.left, 0L, static_cast<LONG>(desc.Width)); + rect.top = clamp(rect.top, 0L, static_cast<LONG>(desc.Height)); + rect.right = clamp(rect.right, 0L, static_cast<LONG>(desc.Width)); + rect.bottom = clamp(rect.bottom, 0L, static_cast<LONG>(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) + lock.Pitch * (rect.bottom - rect.top - 1); + unsigned char *dest = (unsigned char*)pixels; + unsigned short *dest16 = (unsigned short*)pixels; + int inputPitch = -lock.Pitch; + 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 * inputPitch, + (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 * inputPitch); + + a = 1.0f; + b = (rgb & 0x001F) * (1.0f / 0x001F); + g = (rgb & 0x07E0) * (1.0f / 0x07E0); + r = (rgb & 0xF800) * (1.0f / 0xF800); + } + break; + case D3DFMT_A1R5G5B5: + { + unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch); + + a = (argb & 0x8000) ? 1.0f : 0.0f; + b = (argb & 0x001F) * (1.0f / 0x001F); + g = (argb & 0x03E0) * (1.0f / 0x03E0); + r = (argb & 0x7C00) * (1.0f / 0x7C00); + } + break; + case D3DFMT_A8R8G8B8: + { + unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); + + a = (argb & 0xFF000000) * (1.0f / 0xFF000000); + b = (argb & 0x000000FF) * (1.0f / 0x000000FF); + g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00); + r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000); + } + break; + case D3DFMT_X8R8G8B8: + { + unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch); + + a = 1.0f; + b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF); + g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00); + r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000); + } + break; + case D3DFMT_A2R10G10B10: + { + unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); + + a = (argb & 0xC0000000) * (1.0f / 0xC0000000); + b = (argb & 0x000003FF) * (1.0f / 0x000003FF); + g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00); + r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000); + } + break; + case D3DFMT_A32B32G32R32F: + { + // float formats in D3D are stored rgba, rather than the other way round + r = *((float*)(source + 16 * i + j * inputPitch) + 0); + g = *((float*)(source + 16 * i + j * inputPitch) + 1); + b = *((float*)(source + 16 * i + j * inputPitch) + 2); + a = *((float*)(source + 16 * i + j * inputPitch) + 3); + } + break; + case D3DFMT_A16B16G16R16F: + { + // float formats in D3D are stored rgba, rather than the other way round + float abgr[4]; + + D3DXFloat16To32Array(abgr, (D3DXFLOAT16*)(source + 8 * i + j * inputPitch), 4); + + a = abgr[3]; + b = abgr[2]; + g = abgr[1]; + r = abgr[0]; + } + 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) + { + return error(GL_INVALID_FRAMEBUFFER_OPERATION); + } + + 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(); + if (!depthStencil) + { + ERR("Depth stencil pointer unexpectedly null."); + return; + } + + D3DSURFACE_DESC desc; + depthStencil->GetDesc(&desc); + + unsigned int stencilSize = dx2es::GetStencilSize(desc.Format); + stencilUnmasked = (0x1 << stencilSize) - 1; + + if (stencilUnmasked != 0x0) + { + flags |= D3DCLEAR_STENCIL; + } + } + } + + if (mask != 0) + { + return error(GL_INVALID_VALUE); + } + + if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport + { + return; + } + + D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha), + unorm<8>(mState.colorClearValue.red), + unorm<8>(mState.colorClearValue.green), + unorm<8>(mState.colorClearValue.blue)); + float depth = clamp01(mState.depthClearValue); + int stencil = mState.stencilClearValue & 0x000000FF; + + IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget(); + + if (!renderTarget) + { + return; // Context must be lost, return silently + } + + D3DSURFACE_DESC desc; + renderTarget->GetDesc(&desc); + + bool alphaUnmasked = (dx2es::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->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); + device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); + device->SetRenderState(D3DRS_TEXTUREFACTOR, color); + device->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); + + 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, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, mState.colorMaskBlue, mState.colorMaskAlpha)); + } + 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); + device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); + device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); + device->SetRenderState(D3DRS_TEXTUREFACTOR, color); + device->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); + + float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges + quad[0][0] = -0.5f; + quad[0][1] = desc.Height - 0.5f; + quad[0][2] = 0.0f; + quad[0][3] = 1.0f; + + quad[1][0] = desc.Width - 0.5f; + quad[1][1] = desc.Height - 0.5f; + quad[1][2] = 0.0f; + quad[1][3] = 1.0f; + + quad[2][0] = -0.5f; + quad[2][1] = -0.5f; + quad[2][2] = 0.0f; + quad[2][3] = 1.0f; + + quad[3][0] = desc.Width - 0.5f; + quad[3][1] = -0.5f; + quad[3][2] = 0.0f; + quad[3][3] = 1.0f; + + display->startScene(); + device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4])); + + 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); + + GLenum err = applyVertexBuffer(first, count); + if (err != GL_NO_ERROR) + { + return error(err); + } + + applyShaders(); + applyTextures(); + + if (!getCurrentProgram()->validateSamplers(false)) + { + return error(GL_INVALID_OPERATION); + } + + if (!cullSkipsDraw(mode)) + { + display->startScene(); + + device->DrawPrimitive(primitiveType, 0, primitiveCount); + + if (mode == GL_LINE_LOOP) // Draw the last segment separately + { + drawClosingLine(first, first + count - 1); + } + } +} + +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); + } + + GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; + err = applyVertexBuffer(indexInfo.minIndex, vertexCount); + if (err != GL_NO_ERROR) + { + return error(err); + } + + applyShaders(); + applyTextures(); + + if (!getCurrentProgram()->validateSamplers(false)) + { + return error(GL_INVALID_OPERATION); + } + + if (!cullSkipsDraw(mode)) + { + display->startScene(); + + device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, primitiveCount); + + if (mode == GL_LINE_LOOP) // Draw the last segment separately + { + drawClosingLine(count, type, indices); + } + } +} + +void Context::finish() +{ + egl::Display *display = getDisplay(); + IDirect3DDevice9 *device = getDevice(); + IDirect3DQuery9 *occlusionQuery = NULL; + HRESULT result; + + result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery); + if (FAILED(result)) + { + ERR("CreateQuery failed hr=%x\n", result); + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) + { + return error(GL_OUT_OF_MEMORY); + } + ASSERT(false); + return; + } + + IDirect3DStateBlock9 *savedState = NULL; + result = device->CreateStateBlock(D3DSBT_ALL, &savedState); + if (FAILED(result)) + { + ERR("CreateStateBlock failed hr=%x\n", result); + occlusionQuery->Release(); + + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) + { + return error(GL_OUT_OF_MEMORY); + } + ASSERT(false); + return; + } + + result = occlusionQuery->Issue(D3DISSUE_BEGIN); + if (FAILED(result)) + { + ERR("occlusionQuery->Issue(BEGIN) failed hr=%x\n", result); + occlusionQuery->Release(); + savedState->Release(); + ASSERT(false); + return; + } + + // Render something outside the render target + device->SetPixelShader(NULL); + device->SetVertexShader(NULL); + device->SetFVF(D3DFVF_XYZRHW); + float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f}; + display->startScene(); + device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data)); + + result = occlusionQuery->Issue(D3DISSUE_END); + if (FAILED(result)) + { + ERR("occlusionQuery->Issue(END) failed hr=%x\n", result); + occlusionQuery->Release(); + savedState->Apply(); + savedState->Release(); + ASSERT(false); + return; + } + + while ((result = occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH)) == S_FALSE) + { + // Keep polling, but allow other threads to do something useful first + Sleep(0); + } + + occlusionQuery->Release(); + savedState->Apply(); + savedState->Release(); + + if (result == D3DERR_DEVICELOST) + { + error(GL_OUT_OF_MEMORY); + } +} + +void Context::flush() +{ + IDirect3DDevice9 *device = getDevice(); + IDirect3DQuery9 *eventQuery = NULL; + HRESULT result; + + result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery); + if (FAILED(result)) + { + ERR("CreateQuery failed hr=%x\n", result); + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) + { + return error(GL_OUT_OF_MEMORY); + } + ASSERT(false); + return; + } + + result = eventQuery->Issue(D3DISSUE_END); + if (FAILED(result)) + { + ERR("eventQuery->Issue(END) failed hr=%x\n", result); + ASSERT(false); + eventQuery->Release(); + return; + } + + result = eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH); + eventQuery->Release(); + + if (result == D3DERR_DEVICELOST) + { + error(GL_OUT_OF_MEMORY); + } +} + +void Context::drawClosingLine(unsigned int first, unsigned int last) +{ + IDirect3DDevice9 *device = getDevice(); + IDirect3DIndexBuffer9 *indexBuffer = NULL; + bool succeeded = false; + UINT offset; + + if (supports32bitIndices()) + { + const int spaceNeeded = 2 * sizeof(unsigned int); + + if (!mClosingIB) + { + mClosingIB = new StreamingIndexBuffer(device, CLOSING_INDEX_BUFFER_SIZE, D3DFMT_INDEX32); + } + + mClosingIB->reserveSpace(spaceNeeded, GL_UNSIGNED_INT); + + unsigned int *data = static_cast<unsigned int*>(mClosingIB->map(spaceNeeded, &offset)); + if (data) + { + data[0] = last; + data[1] = first; + mClosingIB->unmap(); + offset /= 4; + succeeded = true; + } + } + else + { + const int spaceNeeded = 2 * sizeof(unsigned short); + + if (!mClosingIB) + { + mClosingIB = new StreamingIndexBuffer(device, CLOSING_INDEX_BUFFER_SIZE, D3DFMT_INDEX16); + } + + mClosingIB->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT); + + unsigned short *data = static_cast<unsigned short*>(mClosingIB->map(spaceNeeded, &offset)); + if (data) + { + data[0] = last; + data[1] = first; + mClosingIB->unmap(); + offset /= 2; + succeeded = true; + } + } + + if (succeeded) + { + device->SetIndices(mClosingIB->getBuffer()); + + device->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, last, offset, 1); + } + else + { + ERR("Could not create an index buffer for closing a line loop."); + error(GL_OUT_OF_MEMORY); + } +} + +void Context::drawClosingLine(GLsizei count, GLenum type, const void *indices) +{ + unsigned int first = 0; + unsigned int last = 0; + + if (mState.elementArrayBuffer.get()) + { + Buffer *indexBuffer = mState.elementArrayBuffer.get(); + intptr_t offset = reinterpret_cast<intptr_t>(indices); + indices = static_cast<const GLubyte*>(indexBuffer->data()) + offset; + } + + switch (type) + { + case GL_UNSIGNED_BYTE: + first = static_cast<const GLubyte*>(indices)[0]; + last = static_cast<const GLubyte*>(indices)[count - 1]; + break; + case GL_UNSIGNED_SHORT: + first = static_cast<const GLushort*>(indices)[0]; + last = static_cast<const GLushort*>(indices)[count - 1]; + break; + case GL_UNSIGNED_INT: + first = static_cast<const GLuint*>(indices)[0]; + last = static_cast<const GLuint*>(indices)[count - 1]; + break; + default: UNREACHABLE(); + } + + drawClosingLine(first, last); +} + +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::getMaximumVaryingVectors() const +{ + return mSupportsShaderModel3 ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2; +} + +unsigned int Context::getMaximumVertexTextureImageUnits() const +{ + return mSupportsVertexTexture ? MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF : 0; +} + +unsigned int Context::getMaximumCombinedTextureImageUnits() const +{ + return MAX_TEXTURE_IMAGE_UNITS + getMaximumVertexTextureImageUnits(); +} + +int Context::getMaximumFragmentUniformVectors() const +{ + return mSupportsShaderModel3 ? MAX_FRAGMENT_UNIFORM_VECTORS_SM3 : MAX_FRAGMENT_UNIFORM_VECTORS_SM2; +} + +int Context::getMaxSupportedSamples() const +{ + return mMaxSupportedSamples; +} + +int Context::getNearestSupportedSamples(D3DFORMAT format, int requested) const +{ + if (requested == 0) + { + return requested; + } + + std::map<D3DFORMAT, bool *>::const_iterator itr = mMultiSampleSupport.find(format); + if (itr == mMultiSampleSupport.end()) + { + return -1; + } + + for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i) + { + if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE) + { + return i; + } + } + + return -1; +} + +bool Context::supportsEventQueries() const +{ + return mSupportsEventQueries; +} + +bool Context::supportsCompressedTextures() const +{ + return mSupportsCompressedTextures; +} + +bool Context::supportsFloatTextures() const +{ + return mSupportsFloatTextures; +} + +bool Context::supportsFloatLinearFilter() const +{ + return mSupportsFloatLinearFilter; +} + +bool Context::supportsFloatRenderableTextures() const +{ + return mSupportsFloatRenderableTextures; +} + +bool Context::supportsHalfFloatTextures() const +{ + return mSupportsHalfFloatTextures; +} + +bool Context::supportsHalfFloatLinearFilter() const +{ + return mSupportsHalfFloatLinearFilter; +} + +bool Context::supportsHalfFloatRenderableTextures() const +{ + return mSupportsHalfFloatRenderableTextures; +} + +int Context::getMaximumRenderbufferDimension() const +{ + return mMaxRenderbufferDimension; +} + +int Context::getMaximumTextureDimension() const +{ + return mMaxTextureDimension; +} + +int Context::getMaximumCubeTextureDimension() const +{ + return mMaxCubeTextureDimension; +} + +int Context::getMaximumTextureLevel() const +{ + return mMaxTextureLevel; +} + +bool Context::supportsLuminanceTextures() const +{ + return mSupportsLuminanceTextures; +} + +bool Context::supportsLuminanceAlphaTextures() const +{ + return mSupportsLuminanceAlphaTextures; +} + +bool Context::supports32bitIndices() const +{ + return mSupports32bitIndices; +} + +bool Context::supportsNonPower2Texture() const +{ + return mSupportsNonPower2Texture; +} + +void Context::detachBuffer(GLuint buffer) +{ + // [OpenGL ES 2.0.24] section 2.9 page 22: + // If a buffer object is deleted while it is bound, all bindings to that object in the current context + // (i.e. in the thread that called Delete-Buffers) are reset to zero. + + if (mState.arrayBuffer.id() == buffer) + { + mState.arrayBuffer.set(NULL); + } + + if (mState.elementArrayBuffer.id() == buffer) + { + mState.elementArrayBuffer.set(NULL); + } + + for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++) + { + if (mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer) + { + mState.vertexAttribute[attribute].mBoundBuffer.set(NULL); + } + } +} + +void Context::detachTexture(GLuint texture) +{ + // [OpenGL ES 2.0.24] section 3.8 page 84: + // If a texture object is deleted, it is as if all texture units which are bound to that texture object are + // rebound to texture object zero + + for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) + { + for (int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; sampler++) + { + if (mState.samplerTexture[type][sampler].id() == texture) + { + mState.samplerTexture[type][sampler].set(NULL); + } + } + } + + // [OpenGL ES 2.0.24] section 4.4 page 112: + // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is + // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this + // image was attached in the currently bound framebuffer. + + Framebuffer *readFramebuffer = getReadFramebuffer(); + Framebuffer *drawFramebuffer = getDrawFramebuffer(); + + if (readFramebuffer) + { + readFramebuffer->detachTexture(texture); + } + + if (drawFramebuffer && drawFramebuffer != readFramebuffer) + { + drawFramebuffer->detachTexture(texture); + } +} + +void Context::detachFramebuffer(GLuint framebuffer) +{ + // [OpenGL ES 2.0.24] section 4.4 page 107: + // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though + // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero. + + if (mState.readFramebuffer == framebuffer) + { + bindReadFramebuffer(0); + } + + if (mState.drawFramebuffer == framebuffer) + { + bindDrawFramebuffer(0); + } +} + +void Context::detachRenderbuffer(GLuint renderbuffer) +{ + // [OpenGL ES 2.0.24] section 4.4 page 109: + // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer + // had been executed with the target RENDERBUFFER and name of zero. + + if (mState.renderbuffer.id() == renderbuffer) + { + bindRenderbuffer(0); + } + + // [OpenGL ES 2.0.24] section 4.4 page 111: + // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer, + // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment + // point to which this image was attached in the currently bound framebuffer. + + Framebuffer *readFramebuffer = getReadFramebuffer(); + Framebuffer *drawFramebuffer = getDrawFramebuffer(); + + if (readFramebuffer) + { + readFramebuffer->detachRenderbuffer(renderbuffer); + } + + if (drawFramebuffer && drawFramebuffer != readFramebuffer) + { + drawFramebuffer->detachRenderbuffer(renderbuffer); + } +} + +Texture *Context::getIncompleteTexture(TextureType type) +{ + Texture *t = mIncompleteTextures[type].get(); + + if (t == NULL) + { + static const GLubyte color[] = { 0, 0, 0, 255 }; + + switch (type) + { + default: + UNREACHABLE(); + // default falls through to TEXTURE_2D + + case TEXTURE_2D: + { + Texture2D *incomplete2d = new Texture2D(Texture::INCOMPLETE_TEXTURE_ID); + incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); + t = incomplete2d; + } + break; + + case TEXTURE_CUBE: + { + TextureCubeMap *incompleteCube = new TextureCubeMap(Texture::INCOMPLETE_TEXTURE_ID); + + incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); + incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); + incompleteCube->setImagePosY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); + incompleteCube->setImageNegY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); + incompleteCube->setImagePosZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); + incompleteCube->setImageNegZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); + + t = incompleteCube; + } + break; + } + + mIncompleteTextures[type].set(t); + } + + return t; +} + +bool Context::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->dirtyCurrentValue(index); +} + +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 "; + mExtensionString += "GL_OES_standard_derivatives "; + + if (supportsEventQueries()) + { + mExtensionString += "GL_NV_fence "; + } + + if (supportsCompressedTextures()) + { + mExtensionString += "GL_EXT_texture_compression_dxt1 "; + } + + if (supportsFloatTextures()) + { + mExtensionString += "GL_OES_texture_float "; + } + + if (supportsHalfFloatTextures()) + { + mExtensionString += "GL_OES_texture_half_float "; + } + + if (supportsFloatLinearFilter()) + { + mExtensionString += "GL_OES_texture_float_linear "; + } + + if (supportsHalfFloatLinearFilter()) + { + mExtensionString += "GL_OES_texture_half_float_linear "; + } + + if (getMaxSupportedSamples() != 0) + { + mExtensionString += "GL_ANGLE_framebuffer_multisample "; + } + + if (supports32bitIndices()) + { + mExtensionString += "GL_OES_element_index_uint "; + } + + if (supportsNonPower2Texture()) + { + mExtensionString += "GL_OES_texture_npot "; + } + + 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); + } + + int readBufferWidth = readFramebuffer->getColorbuffer()->getWidth(); + int readBufferHeight = readFramebuffer->getColorbuffer()->getHeight(); + int drawBufferWidth = drawFramebuffer->getColorbuffer()->getWidth(); + int drawBufferHeight = drawFramebuffer->getColorbuffer()->getHeight(); + + RECT sourceRect; + RECT destRect; + + if (srcX0 < srcX1) + { + sourceRect.left = srcX0; + sourceRect.right = srcX1; + destRect.left = dstX0; + destRect.right = dstX1; + } + else + { + sourceRect.left = srcX1; + destRect.left = dstX1; + sourceRect.right = srcX0; + destRect.right = dstX0; + } + + if (srcY0 < srcY1) + { + sourceRect.top = readBufferHeight - srcY1; + destRect.top = drawBufferHeight - dstY1; + sourceRect.bottom = readBufferHeight - srcY0; + destRect.bottom = drawBufferHeight - dstY0; + } + else + { + sourceRect.top = readBufferHeight - srcY0; + destRect.top = drawBufferHeight - dstY0; + sourceRect.bottom = readBufferHeight - srcY1; + destRect.bottom = drawBufferHeight - dstY1; + } + + RECT sourceScissoredRect = sourceRect; + RECT destScissoredRect = destRect; + + if (mState.scissorTest) + { + // Only write to parts of the destination framebuffer which pass the scissor test + // Please note: the destRect is now in D3D-style coordinates, so the *top* of the + // rect will be checked against scissorY, rather than the bottom. + if (destRect.left < mState.scissorX) + { + int xDiff = mState.scissorX - destRect.left; + destScissoredRect.left = mState.scissorX; + sourceScissoredRect.left += xDiff; + } + + if (destRect.right > mState.scissorX + mState.scissorWidth) + { + int xDiff = destRect.right - (mState.scissorX + mState.scissorWidth); + destScissoredRect.right = mState.scissorX + mState.scissorWidth; + sourceScissoredRect.right -= xDiff; + } + + if (destRect.top < mState.scissorY) + { + int yDiff = mState.scissorY - destRect.top; + destScissoredRect.top = mState.scissorY; + sourceScissoredRect.top += yDiff; + } + + if (destRect.bottom > mState.scissorY + mState.scissorHeight) + { + int yDiff = destRect.bottom - (mState.scissorY + mState.scissorHeight); + destScissoredRect.bottom = mState.scissorY + mState.scissorHeight; + sourceScissoredRect.bottom -= yDiff; + } + } + + bool blitRenderTarget = false; + bool blitDepthStencil = false; + + RECT sourceTrimmedRect = sourceScissoredRect; + RECT destTrimmedRect = destScissoredRect; + + // The source & destination rectangles also may need to be trimmed if they fall out of the bounds of + // the actual draw and read surfaces. + if (sourceTrimmedRect.left < 0) + { + int xDiff = 0 - sourceTrimmedRect.left; + sourceTrimmedRect.left = 0; + destTrimmedRect.left += xDiff; + } + + if (sourceTrimmedRect.right > readBufferWidth) + { + int xDiff = sourceTrimmedRect.right - readBufferWidth; + sourceTrimmedRect.right = readBufferWidth; + destTrimmedRect.right -= xDiff; + } + + if (sourceTrimmedRect.top < 0) + { + int yDiff = 0 - sourceTrimmedRect.top; + sourceTrimmedRect.top = 0; + destTrimmedRect.top += yDiff; + } + + if (sourceTrimmedRect.bottom > readBufferHeight) + { + int yDiff = sourceTrimmedRect.bottom - readBufferHeight; + sourceTrimmedRect.bottom = readBufferHeight; + destTrimmedRect.bottom -= yDiff; + } + + if (destTrimmedRect.left < 0) + { + int xDiff = 0 - destTrimmedRect.left; + destTrimmedRect.left = 0; + sourceTrimmedRect.left += xDiff; + } + + if (destTrimmedRect.right > drawBufferWidth) + { + int xDiff = destTrimmedRect.right - drawBufferWidth; + destTrimmedRect.right = drawBufferWidth; + sourceTrimmedRect.right -= xDiff; + } + + if (destTrimmedRect.top < 0) + { + int yDiff = 0 - destTrimmedRect.top; + destTrimmedRect.top = 0; + sourceTrimmedRect.top += yDiff; + } + + if (destTrimmedRect.bottom > drawBufferHeight) + { + int yDiff = destTrimmedRect.bottom - drawBufferHeight; + destTrimmedRect.bottom = drawBufferHeight; + sourceTrimmedRect.bottom -= yDiff; + } + + bool partialBufferCopy = false; + if (sourceTrimmedRect.bottom - sourceTrimmedRect.top < readBufferHeight || + sourceTrimmedRect.right - sourceTrimmedRect.left < readBufferWidth || + destTrimmedRect.bottom - destTrimmedRect.top < drawBufferHeight || + destTrimmedRect.right - destTrimmedRect.left < drawBufferWidth || + sourceTrimmedRect.top != 0 || destTrimmedRect.top != 0 || sourceTrimmedRect.left != 0 || destTrimmedRect.left != 0) + { + partialBufferCopy = true; + } + + if (mask & GL_COLOR_BUFFER_BIT) + { + const bool validReadType = readFramebuffer->getColorbufferType() == GL_TEXTURE_2D || + readFramebuffer->getColorbufferType() == GL_RENDERBUFFER; + const bool validDrawType = drawFramebuffer->getColorbufferType() == GL_TEXTURE_2D || + drawFramebuffer->getColorbufferType() == GL_RENDERBUFFER; + if (!validReadType || !validDrawType || + readFramebuffer->getColorbuffer()->getD3DFormat() != drawFramebuffer->getColorbuffer()->getD3DFormat()) + { + ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation"); + return error(GL_INVALID_OPERATION); + } + + if (partialBufferCopy && readFramebuffer->getSamples() != 0) + { + return error(GL_INVALID_OPERATION); + } + + blitRenderTarget = true; + + } + + if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) + { + 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; + } + } + } +} + +VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0) +{ + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + mVertexDeclCache[i].vertexDeclaration = NULL; + mVertexDeclCache[i].lruCount = 0; + } +} + +VertexDeclarationCache::~VertexDeclarationCache() +{ + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + if (mVertexDeclCache[i].vertexDeclaration) + { + mVertexDeclCache[i].vertexDeclaration->Release(); + } + } +} + +GLenum VertexDeclarationCache::applyDeclaration(TranslatedAttribute attributes[], Program *program) +{ + IDirect3DDevice9 *device = getDevice(); + + D3DVERTEXELEMENT9 elements[MAX_VERTEX_ATTRIBS + 1]; + D3DVERTEXELEMENT9 *element = &elements[0]; + + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + if (attributes[i].active) + { + device->SetStreamSource(i, attributes[i].vertexBuffer, attributes[i].offset, attributes[i].stride); + + element->Stream = i; + element->Offset = 0; + element->Type = attributes[i].type; + element->Method = D3DDECLMETHOD_DEFAULT; + element->Usage = D3DDECLUSAGE_TEXCOORD; + element->UsageIndex = program->getSemanticIndex(i); + element++; + } + } + + static const D3DVERTEXELEMENT9 end = D3DDECL_END(); + *(element++) = end; + + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + VertexDeclCacheEntry *entry = &mVertexDeclCache[i]; + if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration) + { + entry->lruCount = ++mMaxLru; + device->SetVertexDeclaration(entry->vertexDeclaration); + + return GL_NO_ERROR; + } + } + + VertexDeclCacheEntry *lastCache = mVertexDeclCache; + + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + if (mVertexDeclCache[i].lruCount < lastCache->lruCount) + { + lastCache = &mVertexDeclCache[i]; + } + } + + if (lastCache->vertexDeclaration != NULL) + { + lastCache->vertexDeclaration->Release(); + lastCache->vertexDeclaration = NULL; + } + + memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)); + device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration); + device->SetVertexDeclaration(lastCache->vertexDeclaration); + lastCache->lruCount = ++mMaxLru; + + return GL_NO_ERROR; +} + +} + +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 000000000..30026544c --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Context.h @@ -0,0 +1,581 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Context.h: Defines the gl::Context class, managing all GL state and performing +// rendering operations. It is the GLES2 specific implementation of EGLContext. + +#ifndef LIBGLESV2_CONTEXT_H_ +#define LIBGLESV2_CONTEXT_H_ + +#define GL_APICALL +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#define EGLAPI +#include <EGL/egl.h> +#include <d3d9.h> + +#include <map> +#include <hash_map> + +#include "common/angleutils.h" +#include "libGLESv2/ResourceManager.h" +#include "libGLESv2/HandleAllocator.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 StreamingIndexBuffer; +class Stencilbuffer; +class DepthStencilbuffer; +class VertexDataManager; +class IndexDataManager; +class Blit; +class Fence; + +enum +{ + MAX_VERTEX_ATTRIBS = 16, + MAX_VERTEX_UNIFORM_VECTORS = 256 - 2, // 256 is the minimum for SM2, and in practice the maximum for DX9. Reserve space for dx_HalfPixelSize and dx_DepthRange. + MAX_VARYING_VECTORS_SM2 = 8, + MAX_VARYING_VECTORS_SM3 = 10, + MAX_TEXTURE_IMAGE_UNITS = 16, + MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF = 4, // For devices supporting vertex texture fetch + MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF = MAX_TEXTURE_IMAGE_UNITS + MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF, + MAX_FRAGMENT_UNIFORM_VECTORS_SM2 = 32 - 3, // Reserve space for dx_Viewport, dx_Depth, and dx_DepthRange. dx_PointOrLines and dx_FrontCCW use separate bool registers. + MAX_FRAGMENT_UNIFORM_VECTORS_SM3 = 224 - 3, + MAX_DRAW_BUFFERS = 1, + + 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 VertexAttribute +{ + public: + VertexAttribute() : mType(GL_FLOAT), mSize(0), mNormalized(false), mStride(0), mPointer(NULL), mArrayEnabled(false) + { + mCurrentValue[0] = 0.0f; + mCurrentValue[1] = 0.0f; + mCurrentValue[2] = 0.0f; + mCurrentValue[3] = 1.0f; + } + + int typeSize() const + { + switch (mType) + { + case GL_BYTE: return mSize * sizeof(GLbyte); + case GL_UNSIGNED_BYTE: return mSize * sizeof(GLubyte); + case GL_SHORT: return mSize * sizeof(GLshort); + case GL_UNSIGNED_SHORT: return mSize * sizeof(GLushort); + case GL_FIXED: return mSize * sizeof(GLfixed); + case GL_FLOAT: return mSize * sizeof(GLfloat); + default: UNREACHABLE(); return mSize * sizeof(GLfloat); + } + } + + GLsizei stride() const + { + return mStride ? mStride : typeSize(); + } + + // From glVertexAttribPointer + GLenum mType; + GLint mSize; + bool mNormalized; + GLsizei mStride; // 0 means natural stride + + union + { + const void *mPointer; + intptr_t mOffset; + }; + + BindingPointer<Buffer> mBoundBuffer; // Captured when glVertexAttribPointer is called. + + bool mArrayEnabled; // From glEnable/DisableVertexAttribArray + float mCurrentValue[4]; // From glVertexAttrib +}; + +typedef VertexAttribute VertexAttributeArray[MAX_VERTEX_ATTRIBS]; + +// Helper structure to store all raw state +struct State +{ + Color colorClearValue; + GLclampf depthClearValue; + int stencilClearValue; + + bool cullFace; + GLenum cullMode; + GLenum frontFace; + bool depthTest; + GLenum depthFunc; + bool blend; + GLenum sourceBlendRGB; + GLenum destBlendRGB; + GLenum sourceBlendAlpha; + GLenum destBlendAlpha; + GLenum blendEquationRGB; + GLenum blendEquationAlpha; + Color blendColor; + bool stencilTest; + GLenum stencilFunc; + GLint stencilRef; + GLuint stencilMask; + GLenum stencilFail; + GLenum stencilPassDepthFail; + GLenum stencilPassDepthPass; + GLuint stencilWritemask; + GLenum stencilBackFunc; + GLint stencilBackRef; + GLuint stencilBackMask; + GLenum stencilBackFail; + GLenum stencilBackPassDepthFail; + GLenum stencilBackPassDepthPass; + GLuint stencilBackWritemask; + bool polygonOffsetFill; + GLfloat polygonOffsetFactor; + GLfloat polygonOffsetUnits; + bool sampleAlphaToCoverage; + bool sampleCoverage; + GLclampf sampleCoverageValue; + bool sampleCoverageInvert; + bool scissorTest; + bool dither; + + GLfloat lineWidth; + + GLenum generateMipmapHint; + GLenum fragmentShaderDerivativeHint; + + GLint viewportX; + GLint viewportY; + GLsizei viewportWidth; + GLsizei viewportHeight; + float zNear; + float zFar; + + GLint scissorX; + GLint scissorY; + GLsizei scissorWidth; + GLsizei scissorHeight; + + bool colorMaskRed; + bool colorMaskGreen; + bool colorMaskBlue; + bool colorMaskAlpha; + bool depthMask; + + unsigned int activeSampler; // Active texture unit selector - GL_TEXTURE0 + BindingPointer<Buffer> arrayBuffer; + BindingPointer<Buffer> elementArrayBuffer; + GLuint readFramebuffer; + GLuint drawFramebuffer; + BindingPointer<Renderbuffer> renderbuffer; + GLuint currentProgram; + + VertexAttribute vertexAttribute[MAX_VERTEX_ATTRIBS]; + BindingPointer<Texture> samplerTexture[TEXTURE_TYPE_COUNT][MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF]; + + GLint unpackAlignment; + GLint packAlignment; +}; + +// Helper class to construct and cache vertex declarations +class VertexDeclarationCache +{ + public: + VertexDeclarationCache(); + ~VertexDeclarationCache(); + + GLenum applyDeclaration(TranslatedAttribute attributes[], Program *program); + + private: + UINT mMaxLru; + + enum { NUM_VERTEX_DECL_CACHE_ENTRIES = 16 }; + + struct VertexDeclCacheEntry + { + D3DVERTEXELEMENT9 cachedElements[MAX_VERTEX_ATTRIBS + 1]; + UINT lruCount; + IDirect3DVertexDeclaration9 *vertexDeclaration; + } mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES]; +}; + +class Context +{ + public: + Context(const egl::Config *config, const gl::Context *shareContext); + + ~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 setFragmentShaderDerivativeHint(GLenum hint); + + void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height); + + void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height); + + void setColorMask(bool red, bool green, bool blue, bool alpha); + void setDepthMask(bool mask); + + void setActiveSampler(unsigned int active); + + GLuint getReadFramebufferHandle() const; + GLuint getDrawFramebufferHandle() const; + GLuint getRenderbufferHandle() const; + + GLuint getArrayBufferHandle() const; + + void setEnableVertexAttribArray(unsigned int attribNum, bool enabled); + const VertexAttribute &getVertexAttribState(unsigned int attribNum); + void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, + bool normalized, GLsizei stride, const void *pointer); + const void *getVertexAttribPointer(unsigned int attribNum) const; + + const VertexAttributeArray &getVertexAttributes(); + + void setUnpackAlignment(GLint alignment); + GLint getUnpackAlignment() const; + + void setPackAlignment(GLint alignment); + GLint getPackAlignment() const; + + // These create and destroy methods are merely pass-throughs to + // ResourceManager, which owns these object types + GLuint createBuffer(); + GLuint createShader(GLenum type); + GLuint createProgram(); + GLuint createTexture(); + GLuint createRenderbuffer(); + + void deleteBuffer(GLuint buffer); + void deleteShader(GLuint shader); + void deleteProgram(GLuint program); + void deleteTexture(GLuint texture); + void deleteRenderbuffer(GLuint renderbuffer); + + // Framebuffers are owned by the Context, so these methods do not pass through + GLuint createFramebuffer(); + void deleteFramebuffer(GLuint framebuffer); + + // Fences are owned by the Context. + GLuint createFence(); + void deleteFence(GLuint fence); + + 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); + Fence *getFence(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, TextureType type); + Framebuffer *getReadFramebuffer(); + Framebuffer *getDrawFramebuffer(); + + bool getFloatv(GLenum pname, GLfloat *params); + bool getIntegerv(GLenum pname, GLint *params); + bool getBooleanv(GLenum pname, GLboolean *params); + + bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams); + + void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, 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(); + + // Draw the last segment of a line loop + void drawClosingLine(unsigned int first, unsigned int last); + void drawClosingLine(GLsizei count, GLenum type, const void *indices); + + void recordInvalidEnum(); + void recordInvalidValue(); + void recordInvalidOperation(); + void recordOutOfMemory(); + void recordInvalidFramebufferOperation(); + + GLenum getError(); + + bool supportsShaderModel3() const; + int getMaximumVaryingVectors() const; + unsigned int getMaximumVertexTextureImageUnits() const; + unsigned int getMaximumCombinedTextureImageUnits() const; + int getMaximumFragmentUniformVectors() const; + int getMaximumRenderbufferDimension() const; + int getMaximumTextureDimension() const; + int getMaximumCubeTextureDimension() const; + int getMaximumTextureLevel() const; + GLsizei getMaxSupportedSamples() const; + int getNearestSupportedSamples(D3DFORMAT format, int requested) const; + const char *getExtensionString() const; + bool supportsEventQueries() const; + bool supportsCompressedTextures() const; + bool supportsFloatTextures() const; + bool supportsFloatLinearFilter() const; + bool supportsFloatRenderableTextures() const; + bool supportsHalfFloatTextures() const; + bool supportsHalfFloatLinearFilter() const; + bool supportsHalfFloatRenderableTextures() const; + bool supportsLuminanceTextures() const; + bool supportsLuminanceAlphaTextures() const; + bool supports32bitIndices() const; + bool supportsNonPower2Texture() const; + + void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask); + + Blit *getBlitter() { return mBlit; } + + const D3DCAPS9 &getDeviceCaps() { return mDeviceCaps; } + + private: + DISALLOW_COPY_AND_ASSIGN(Context); + + bool applyRenderTarget(bool ignoreViewport); + void applyState(GLenum drawMode); + GLenum applyVertexBuffer(GLint first, GLsizei count); + GLenum applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); + void applyShaders(); + void applyTextures(); + void applyTextures(SamplerType type); + + void detachBuffer(GLuint buffer); + void detachTexture(GLuint texture); + void detachFramebuffer(GLuint framebuffer); + void detachRenderbuffer(GLuint renderbuffer); + + Texture *getIncompleteTexture(TextureType type); + + bool cullSkipsDraw(GLenum drawMode); + bool isTriangleMode(GLenum drawMode); + + const egl::Config *const mConfig; + + State mState; + + BindingPointer<Texture2D> mTexture2DZero; + BindingPointer<TextureCubeMap> mTextureCubeMapZero; + + typedef stdext::hash_map<GLuint, Framebuffer*> FramebufferMap; + FramebufferMap mFramebufferMap; + HandleAllocator mFramebufferHandleAllocator; + + typedef stdext::hash_map<GLuint, Fence*> FenceMap; + FenceMap mFenceMap; + HandleAllocator mFenceHandleAllocator; + + void initExtensionString(); + std::string mExtensionString; + + VertexDataManager *mVertexDataManager; + IndexDataManager *mIndexDataManager; + + Blit *mBlit; + + StreamingIndexBuffer *mClosingIB; + + BindingPointer<Texture> mIncompleteTextures[TEXTURE_TYPE_COUNT]; + + // Recorded errors + bool mInvalidEnum; + bool mInvalidValue; + bool mInvalidOperation; + bool mOutOfMemory; + bool mInvalidFramebufferOperation; + + bool mHasBeenCurrent; + + unsigned int mAppliedTextureSerialPS[MAX_TEXTURE_IMAGE_UNITS]; + unsigned int mAppliedTextureSerialVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF]; + unsigned int mAppliedProgramSerial; + unsigned int mAppliedRenderTargetSerial; + unsigned int mAppliedDepthbufferSerial; + unsigned int mAppliedStencilbufferSerial; + bool mDepthStencilInitialized; + + bool mSupportsShaderModel3; + bool mSupportsVertexTexture; + bool mSupportsNonPower2Texture; + int mMaxRenderbufferDimension; + int mMaxTextureDimension; + int mMaxCubeTextureDimension; + int mMaxTextureLevel; + std::map<D3DFORMAT, bool *> mMultiSampleSupport; + GLsizei mMaxSupportedSamples; + bool mSupportsEventQueries; + bool mSupportsCompressedTextures; + bool mSupportsFloatTextures; + bool mSupportsFloatLinearFilter; + bool mSupportsFloatRenderableTextures; + bool mSupportsHalfFloatTextures; + bool mSupportsHalfFloatLinearFilter; + bool mSupportsHalfFloatRenderableTextures; + bool mSupportsLuminanceTextures; + bool mSupportsLuminanceAlphaTextures; + bool mSupports32bitIndices; + + // state caching flags + bool mClearStateDirty; + bool mCullStateDirty; + bool mDepthStateDirty; + bool mMaskStateDirty; + bool mPixelPackingStateDirty; + bool mBlendStateDirty; + bool mStencilStateDirty; + bool mPolygonOffsetStateDirty; + bool mScissorStateDirty; + bool mSampleStateDirty; + bool mFrontFaceDirty; + bool mDitherStateDirty; + + IDirect3DStateBlock9 *mMaskedClearSavedState; + + D3DCAPS9 mDeviceCaps; + + ResourceManager *mResourceManager; + + VertexDeclarationCache mVertexDeclarationCache; +}; +} + +extern "C" +{ +// Exported functions for use by EGL +gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext); +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); +void __stdcall glBindTexImage(egl::Surface *surface); +} + +#endif // INCLUDE_CONTEXT_H_ diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Fence.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Fence.cpp new file mode 100644 index 000000000..7fbcb6ad3 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Fence.cpp @@ -0,0 +1,134 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Fence.cpp: Implements the gl::Fence class, which supports the GL_NV_fence extension. + +#include "libGLESv2/Fence.h" + +#include "libGLESv2/main.h" + +namespace gl +{ + +Fence::Fence() +{ + mQuery = NULL; + mCondition = GL_NONE; + mStatus = GL_FALSE; +} + +Fence::~Fence() +{ + if (mQuery != NULL) + { + mQuery->Release(); + mQuery = NULL; + } +} + +GLboolean Fence::isFence() +{ + // GL_NV_fence spec: + // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence. + return mQuery != NULL; +} + +void Fence::setFence(GLenum condition) +{ + if (mQuery != NULL) + { + mQuery->Release(); + mQuery = NULL; + } + + if (FAILED(getDevice()->CreateQuery(D3DQUERYTYPE_EVENT, &mQuery))) + { + return error(GL_OUT_OF_MEMORY); + } + + HRESULT result = mQuery->Issue(D3DISSUE_END); + ASSERT(SUCCEEDED(result)); + + mCondition = condition; + mStatus = GL_FALSE; +} + +GLboolean Fence::testFence() +{ + if (mQuery == NULL) + { + return error(GL_INVALID_OPERATION, GL_TRUE); + } + + HRESULT result = mQuery->GetData(NULL, 0, D3DGETDATA_FLUSH); + + if (result == D3DERR_DEVICELOST) + { + return error(GL_OUT_OF_MEMORY, GL_TRUE); + } + + ASSERT(result == S_OK || result == S_FALSE); + mStatus = result == S_OK; + return mStatus; +} + +void Fence::finishFence() +{ + if (mQuery == NULL) + { + return error(GL_INVALID_OPERATION); + } + + while (!testFence()) + { + Sleep(0); + } +} + +void Fence::getFenceiv(GLenum pname, GLint *params) +{ + if (mQuery == NULL) + { + return error(GL_INVALID_OPERATION); + } + + switch (pname) + { + case GL_FENCE_STATUS_NV: + { + // GL_NV_fence spec: + // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV + // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence. + if (mStatus) + { + params[0] = GL_TRUE; + return; + } + + HRESULT result = mQuery->GetData(NULL, 0, 0); + + if (result == D3DERR_DEVICELOST) + { + params[0] = GL_TRUE; + return error(GL_OUT_OF_MEMORY); + } + + ASSERT(result == S_OK || result == S_FALSE); + mStatus = result == S_OK; + params[0] = mStatus; + + break; + } + case GL_FENCE_CONDITION_NV: + params[0] = mCondition; + break; + default: + return error(GL_INVALID_ENUM); + break; + } +} + +} diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Fence.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Fence.h new file mode 100644 index 000000000..17bad78ea --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Fence.h @@ -0,0 +1,43 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Fence.h: Defines the gl::Fence class, which supports the GL_NV_fence extension. + +#ifndef LIBGLESV2_FENCE_H_ +#define LIBGLESV2_FENCE_H_ + +#define GL_APICALL +#include <GLES2/gl2.h> +#include <d3d9.h> + +#include "common/angleutils.h" + +namespace gl +{ + +class Fence +{ + public: + Fence(); + virtual ~Fence(); + + GLboolean isFence(); + void setFence(GLenum condition); + GLboolean testFence(); + void finishFence(); + void getFenceiv(GLenum pname, GLint *params); + + private: + DISALLOW_COPY_AND_ASSIGN(Fence); + + IDirect3DQuery9* mQuery; + GLenum mCondition; + GLboolean mStatus; +}; + +} + +#endif // LIBGLESV2_FENCE_H_ diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.cpp new file mode 100644 index 000000000..0f7ec20f8 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.cpp @@ -0,0 +1,454 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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)->getRenderbuffer(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; +} + +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 (mColorbufferType == GL_RENDERBUFFER) + { + if (!gl::IsColorRenderable(colorbuffer->getInternalFormat())) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + else if (IsTextureTarget(mColorbufferType)) + { + if (IsCompressed(colorbuffer->getInternalFormat())) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + if ((colorbuffer->getType() == GL_FLOAT && !getContext()->supportsFloatRenderableTextures()) || + (colorbuffer->getType() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatRenderableTextures())) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + if (colorbuffer->getInternalFormat() == GL_LUMINANCE || colorbuffer->getInternalFormat() == GL_LUMINANCE_ALPHA) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + } + else UNREACHABLE(); + + 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) + { + if (mDepthbufferType != GL_RENDERBUFFER) + { + return GL_FRAMEBUFFER_UNSUPPORTED; // Requires GL_OES_depth_texture + } + + 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 (mStencilbufferType != GL_NONE) + { + if (mStencilbufferType != GL_RENDERBUFFER) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + 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 (mDepthbufferType == GL_RENDERBUFFER && mStencilbufferType == GL_RENDERBUFFER) + { + if (depthbuffer->getInternalFormat() != GL_DEPTH24_STENCIL8_OES || + stencilbuffer->getInternalFormat() != 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 = (depthStencil->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE; + mStencilbufferType = (depthStencil->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE; + + 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() +{ + // The default framebuffer should always be complete + ASSERT(Framebuffer::completeness() == GL_FRAMEBUFFER_COMPLETE); + + 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 000000000..cf51658dd --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.h @@ -0,0 +1,95 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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(); + 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/HandleAllocator.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/HandleAllocator.cpp new file mode 100644 index 000000000..c498f8a17 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/HandleAllocator.cpp @@ -0,0 +1,63 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// HandleAllocator.cpp: Implements the gl::HandleAllocator class, which is used +// to allocate GL handles. + +#include "libGLESv2/HandleAllocator.h" + +#include "libGLESv2/main.h" + +namespace gl +{ + +HandleAllocator::HandleAllocator() : mBaseValue(1), mNextValue(1) +{ +} + +HandleAllocator::~HandleAllocator() +{ +} + +void HandleAllocator::setBaseHandle(GLuint value) +{ + ASSERT(mBaseValue == mNextValue); + mBaseValue = value; + mNextValue = value; +} + +GLuint HandleAllocator::allocate() +{ + if (mFreeValues.size()) + { + GLuint handle = mFreeValues.back(); + mFreeValues.pop_back(); + return handle; + } + return mNextValue++; +} + +void HandleAllocator::release(GLuint handle) +{ + if (handle == mNextValue - 1) + { + // Don't drop below base value + if(mNextValue > mBaseValue) + { + mNextValue--; + } + } + else + { + // Only free handles that we own - don't drop below the base value + if (handle >= mBaseValue) + { + mFreeValues.push_back(handle); + } + } +} + +} diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/HandleAllocator.h b/Source/ThirdParty/ANGLE/src/libGLESv2/HandleAllocator.h new file mode 100644 index 000000000..a92e1684d --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/HandleAllocator.h @@ -0,0 +1,45 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// HandleAllocator.h: Defines the gl::HandleAllocator class, which is used to +// allocate GL handles. + +#ifndef LIBGLESV2_HANDLEALLOCATOR_H_ +#define LIBGLESV2_HANDLEALLOCATOR_H_ + +#define GL_APICALL +#include <GLES2/gl2.h> + +#include <vector> + +#include "common/angleutils.h" + +namespace gl +{ + +class HandleAllocator +{ + public: + HandleAllocator(); + virtual ~HandleAllocator(); + + void setBaseHandle(GLuint value); + + GLuint allocate(); + void release(GLuint handle); + + private: + DISALLOW_COPY_AND_ASSIGN(HandleAllocator); + + GLuint mBaseValue; + GLuint mNextValue; + typedef std::vector<GLuint> HandleList; + HandleList mFreeValues; +}; + +} + +#endif // LIBGLESV2_HANDLEALLOCATOR_H_ diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/IndexDataManager.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/IndexDataManager.cpp new file mode 100644 index 000000000..5b939b8a9 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/IndexDataManager.cpp @@ -0,0 +1,404 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexDataManager.cpp: Defines the IndexDataManager, a class that +// runs the Buffer translation process for index buffers. + +#include "libGLESv2/IndexDataManager.h" + +#include "common/debug.h" + +#include "libGLESv2/Buffer.h" +#include "libGLESv2/mathutil.h" +#include "libGLESv2/main.h" + +namespace +{ + enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) }; +} + +namespace gl +{ + +IndexDataManager::IndexDataManager(Context *context, IDirect3DDevice9 *device) : mDevice(device) +{ + mStreamingBufferShort = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16); + + if (context->supports32bitIndices()) + { + mStreamingBufferInt = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32); + + if (!mStreamingBufferInt) + { + // Don't leave it in a half-initialized state + delete mStreamingBufferShort; + mStreamingBufferShort = NULL; + } + } + else + { + mStreamingBufferInt = NULL; + } + + if (!mStreamingBufferShort) + { + ERR("Failed to allocate the streaming index buffer(s)."); + } +} + +IndexDataManager::~IndexDataManager() +{ + delete mStreamingBufferShort; + delete mStreamingBufferInt; +} + +void convertIndices(GLenum type, const void *input, GLsizei count, void *output) +{ + if (type == GL_UNSIGNED_BYTE) + { + const GLubyte *in = static_cast<const GLubyte*>(input); + GLushort *out = static_cast<GLushort*>(output); + + for (GLsizei i = 0; i < count; i++) + { + out[i] = in[i]; + } + } + else if (type == GL_UNSIGNED_INT) + { + memcpy(output, input, count * sizeof(GLuint)); + } + else if (type == GL_UNSIGNED_SHORT) + { + memcpy(output, input, count * sizeof(GLushort)); + } + else UNREACHABLE(); +} + +template <class IndexType> +void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +{ + *minIndex = indices[0]; + *maxIndex = indices[0]; + + for (GLsizei i = 0; i < count; i++) + { + if (*minIndex > indices[i]) *minIndex = indices[i]; + if (*maxIndex < indices[i]) *maxIndex = indices[i]; + } +} + +void computeRange(GLenum type, const void *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +{ + if (type == GL_UNSIGNED_BYTE) + { + computeRange(static_cast<const GLubyte*>(indices), count, minIndex, maxIndex); + } + else if (type == GL_UNSIGNED_INT) + { + computeRange(static_cast<const GLuint*>(indices), count, minIndex, maxIndex); + } + else if (type == GL_UNSIGNED_SHORT) + { + computeRange(static_cast<const GLushort*>(indices), count, minIndex, maxIndex); + } + else UNREACHABLE(); +} + +GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const void *indices, TranslatedIndexData *translated) +{ + if (!mStreamingBufferShort) + { + return GL_OUT_OF_MEMORY; + } + + D3DFORMAT format = (type == GL_UNSIGNED_INT) ? D3DFMT_INDEX32 : D3DFMT_INDEX16; + intptr_t offset = reinterpret_cast<intptr_t>(indices); + bool alignedOffset = false; + + if (buffer != NULL) + { + switch (type) + { + case GL_UNSIGNED_BYTE: alignedOffset = (offset % sizeof(GLubyte) == 0); break; + case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break; + case GL_UNSIGNED_INT: alignedOffset = (offset % sizeof(GLuint) == 0); break; + default: UNREACHABLE(); alignedOffset = false; + } + + if (typeSize(type) * count + offset > static_cast<std::size_t>(buffer->size())) + { + return GL_INVALID_OPERATION; + } + + indices = static_cast<const GLubyte*>(buffer->data()) + offset; + } + + StreamingIndexBuffer *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort; + + StaticIndexBuffer *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL; + IndexBuffer *indexBuffer = streamingBuffer; + UINT streamOffset = 0; + + if (staticBuffer && staticBuffer->lookupType(type) && alignedOffset) + { + indexBuffer = staticBuffer; + streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex); + + if (streamOffset == -1) + { + streamOffset = (offset / typeSize(type)) * indexSize(format); + computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); + staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset); + } + } + else + { + int convertCount = count; + + if (staticBuffer) + { + if (staticBuffer->size() == 0 && alignedOffset) + { + indexBuffer = staticBuffer; + convertCount = buffer->size() / typeSize(type); + } + else + { + buffer->invalidateStaticData(); + staticBuffer = NULL; + } + } + + void *output = NULL; + + if (indexBuffer) + { + indexBuffer->reserveSpace(convertCount * indexSize(format), type); + output = indexBuffer->map(indexSize(format) * convertCount, &streamOffset); + } + + if (output == NULL) + { + ERR("Failed to map index buffer."); + return GL_OUT_OF_MEMORY; + } + + convertIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output); + indexBuffer->unmap(); + + computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); + + if (staticBuffer) + { + streamOffset = (offset / typeSize(type)) * indexSize(format); + staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset); + } + } + + translated->indexBuffer = indexBuffer->getBuffer(); + translated->startIndex = streamOffset / indexSize(format); + + if (buffer) + { + buffer->promoteStaticUsage(count * typeSize(type)); + } + + return GL_NO_ERROR; +} + +std::size_t IndexDataManager::indexSize(D3DFORMAT format) const +{ + return (format == D3DFMT_INDEX32) ? sizeof(unsigned int) : sizeof(unsigned short); +} + +std::size_t IndexDataManager::typeSize(GLenum type) const +{ + switch (type) + { + case GL_UNSIGNED_INT: return sizeof(GLuint); + case GL_UNSIGNED_SHORT: return sizeof(GLushort); + case GL_UNSIGNED_BYTE: return sizeof(GLubyte); + default: UNREACHABLE(); return sizeof(GLushort); + } +} + +IndexBuffer::IndexBuffer(IDirect3DDevice9 *device, UINT size, D3DFORMAT format) : mDevice(device), mBufferSize(size), mIndexBuffer(NULL) +{ + if (size > 0) + { + D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); + HRESULT result = device->CreateIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, pool, &mIndexBuffer, NULL); + + if (FAILED(result)) + { + ERR("Out of memory allocating an index buffer of size %lu.", size); + } + } +} + +IndexBuffer::~IndexBuffer() +{ + if (mIndexBuffer) + { + mIndexBuffer->Release(); + } +} + +IDirect3DIndexBuffer9 *IndexBuffer::getBuffer() const +{ + return mIndexBuffer; +} + +void IndexBuffer::unmap() +{ + if (mIndexBuffer) + { + mIndexBuffer->Unlock(); + } +} + +StreamingIndexBuffer::StreamingIndexBuffer(IDirect3DDevice9 *device, UINT initialSize, D3DFORMAT format) : IndexBuffer(device, initialSize, format) +{ + mWritePosition = 0; +} + +StreamingIndexBuffer::~StreamingIndexBuffer() +{ +} + +void *StreamingIndexBuffer::map(UINT requiredSpace, UINT *offset) +{ + void *mapPtr = NULL; + + if (mIndexBuffer) + { + HRESULT result = mIndexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE); + + if (FAILED(result)) + { + ERR(" Lock failed with error 0x%08x", result); + return NULL; + } + + *offset = mWritePosition; + mWritePosition += requiredSpace; + } + + return mapPtr; +} + +void StreamingIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type) +{ + if (requiredSpace > mBufferSize) + { + if (mIndexBuffer) + { + mIndexBuffer->Release(); + mIndexBuffer = NULL; + } + + mBufferSize = std::max(requiredSpace, 2 * mBufferSize); + + D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); + HRESULT result = mDevice->CreateIndexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL); + + if (FAILED(result)) + { + ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize); + } + + mWritePosition = 0; + } + else if (mWritePosition + requiredSpace > mBufferSize) // Recycle + { + void *dummy; + mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); + mIndexBuffer->Unlock(); + + mWritePosition = 0; + } +} + +StaticIndexBuffer::StaticIndexBuffer(IDirect3DDevice9 *device) : IndexBuffer(device, 0, D3DFMT_UNKNOWN) +{ + mCacheType = GL_NONE; +} + +StaticIndexBuffer::~StaticIndexBuffer() +{ +} + +void *StaticIndexBuffer::map(UINT requiredSpace, UINT *offset) +{ + void *mapPtr = NULL; + + if (mIndexBuffer) + { + HRESULT result = mIndexBuffer->Lock(0, requiredSpace, &mapPtr, 0); + + if (FAILED(result)) + { + ERR(" Lock failed with error 0x%08x", result); + return NULL; + } + + *offset = 0; + } + + return mapPtr; +} + +void StaticIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type) +{ + if (!mIndexBuffer && mBufferSize == 0) + { + D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_WRITEONLY); + HRESULT result = mDevice->CreateIndexBuffer(requiredSpace, D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL); + + if (FAILED(result)) + { + ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize); + } + + mBufferSize = requiredSpace; + mCacheType = type; + } + else if (mIndexBuffer && mBufferSize >= requiredSpace && mCacheType == type) + { + // Already allocated + } + else UNREACHABLE(); // Static index buffers can't be resized +} + +bool StaticIndexBuffer::lookupType(GLenum type) +{ + return mCacheType == type; +} + +UINT StaticIndexBuffer::lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex) +{ + for (unsigned int range = 0; range < mCache.size(); range++) + { + if (mCache[range].offset == offset && mCache[range].count == count) + { + *minIndex = mCache[range].minIndex; + *maxIndex = mCache[range].maxIndex; + + return mCache[range].streamOffset; + } + } + + return -1; +} + +void StaticIndexBuffer::addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset) +{ + IndexRange indexRange = {offset, count, minIndex, maxIndex, streamOffset}; + mCache.push_back(indexRange); +} + +} diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/IndexDataManager.h b/Source/ThirdParty/ANGLE/src/libGLESv2/IndexDataManager.h new file mode 100644 index 000000000..814f41040 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/IndexDataManager.h @@ -0,0 +1,120 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexDataManager.h: Defines the IndexDataManager, a class that +// runs the Buffer translation process for index buffers. + +#ifndef LIBGLESV2_INDEXDATAMANAGER_H_ +#define LIBGLESV2_INDEXDATAMANAGER_H_ + +#include <vector> +#include <cstddef> + +#define GL_APICALL +#include <GLES2/gl2.h> + +#include "libGLESv2/Context.h" + +namespace gl +{ + +struct TranslatedIndexData +{ + UINT minIndex; + UINT maxIndex; + UINT startIndex; + + IDirect3DIndexBuffer9 *indexBuffer; +}; + +class IndexBuffer +{ + public: + IndexBuffer(IDirect3DDevice9 *device, UINT size, D3DFORMAT format); + virtual ~IndexBuffer(); + + UINT size() const { return mBufferSize; } + virtual void *map(UINT requiredSpace, UINT *offset) = 0; + void unmap(); + virtual void reserveSpace(UINT requiredSpace, GLenum type) = 0; + + IDirect3DIndexBuffer9 *getBuffer() const; + + protected: + IDirect3DDevice9 *const mDevice; + + IDirect3DIndexBuffer9 *mIndexBuffer; + UINT mBufferSize; + + private: + DISALLOW_COPY_AND_ASSIGN(IndexBuffer); +}; + +class StreamingIndexBuffer : public IndexBuffer +{ + public: + StreamingIndexBuffer(IDirect3DDevice9 *device, UINT initialSize, D3DFORMAT format); + ~StreamingIndexBuffer(); + + virtual void *map(UINT requiredSpace, UINT *offset); + virtual void reserveSpace(UINT requiredSpace, GLenum type); + + private: + UINT mWritePosition; +}; + +class StaticIndexBuffer : public IndexBuffer +{ + public: + explicit StaticIndexBuffer(IDirect3DDevice9 *device); + ~StaticIndexBuffer(); + + virtual void *map(UINT requiredSpace, UINT *offset); + virtual void reserveSpace(UINT requiredSpace, GLenum type); + + bool lookupType(GLenum type); + UINT lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex); // Returns the offset into the index buffer, or -1 if not found + void addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset); + + private: + GLenum mCacheType; + + struct IndexRange + { + intptr_t offset; + GLsizei count; + + UINT minIndex; + UINT maxIndex; + UINT streamOffset; + }; + + std::vector<IndexRange> mCache; +}; + +class IndexDataManager +{ + public: + IndexDataManager(Context *context, IDirect3DDevice9 *evice); + virtual ~IndexDataManager(); + + GLenum prepareIndexData(GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices, TranslatedIndexData *translated); + + private: + DISALLOW_COPY_AND_ASSIGN(IndexDataManager); + + std::size_t typeSize(GLenum type) const; + std::size_t indexSize(D3DFORMAT format) const; + + IDirect3DDevice9 *const mDevice; + + StreamingIndexBuffer *mStreamingBufferShort; + StreamingIndexBuffer *mStreamingBufferInt; +}; + +} + +#endif // LIBGLESV2_INDEXDATAMANAGER_H_ diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Program.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Program.cpp new file mode 100644 index 000000000..0a25bc2af --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Program.cpp @@ -0,0 +1,3021 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// 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" + +#include <string> + +#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) +#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 +#endif + +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), mSerial(issueSerial()) +{ + mFragmentShader = NULL; + mVertexShader = NULL; + + mPixelExecutable = NULL; + mVertexExecutable = NULL; + mConstantTablePS = NULL; + mConstantTableVS = NULL; + + mInfoLog = NULL; + mValidated = false; + + unlink(); + + mDeleteStatus = false; + + mRefCount = 0; +} + +Program::~Program() +{ + unlink(true); + + if (mVertexShader != NULL) + { + mVertexShader->release(); + } + + if (mFragmentShader != NULL) + { + mFragmentShader->release(); + } +} + +bool Program::attachShader(Shader *shader) +{ + if (shader->getType() == GL_VERTEX_SHADER) + { + if (mVertexShader) + { + return false; + } + + mVertexShader = (VertexShader*)shader; + mVertexShader->addRef(); + } + else if (shader->getType() == GL_FRAGMENT_SHADER) + { + if (mFragmentShader) + { + return false; + } + + mFragmentShader = (FragmentShader*)shader; + mFragmentShader->addRef(); + } + else UNREACHABLE(); + + return true; +} + +bool Program::detachShader(Shader *shader) +{ + if (shader->getType() == GL_VERTEX_SHADER) + { + if (mVertexShader != shader) + { + return false; + } + + mVertexShader->release(); + mVertexShader = NULL; + } + else if (shader->getType() == GL_FRAGMENT_SHADER) + { + if (mFragmentShader != shader) + { + return false; + } + + mFragmentShader->release(); + mFragmentShader = NULL; + } + else UNREACHABLE(); + + 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) +{ + ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS); + + return mSemanticIndex[attributeIndex]; +} + +// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler +// index (0-15 for the pixel shader and 0-3 for the vertex shader). +GLint Program::getSamplerMapping(SamplerType type, unsigned int samplerIndex) +{ + GLuint logicalTextureUnit = -1; + + switch (type) + { + case SAMPLER_PIXEL: + ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0])); + + if (mSamplersPS[samplerIndex].active) + { + logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit; + } + break; + case SAMPLER_VERTEX: + ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0])); + + if (mSamplersVS[samplerIndex].active) + { + logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit; + } + break; + default: UNREACHABLE(); + } + + if (logicalTextureUnit >= 0 && logicalTextureUnit < getContext()->getMaximumCombinedTextureImageUnits()) + { + return logicalTextureUnit; + } + + return -1; +} + +// Returns the texture type for a given Direct3D 9 sampler type and +// index (0-15 for the pixel shader and 0-3 for the vertex shader). +TextureType Program::getSamplerTextureType(SamplerType type, unsigned int samplerIndex) +{ + switch (type) + { + case SAMPLER_PIXEL: + ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0])); + ASSERT(mSamplersPS[samplerIndex].active); + return mSamplersPS[samplerIndex].textureType; + case SAMPLER_VERTEX: + ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0])); + ASSERT(mSamplersVS[samplerIndex].active); + return mSamplersVS[samplerIndex].textureType; + default: UNREACHABLE(); + } + + return TEXTURE_2D; +} + +GLint Program::getUniformLocation(const char *name, bool decorated) +{ + std::string _name = decorated ? name : decorate(name); + int subscript = 0; + + // Strip any trailing array operator and retrieve the subscript + size_t open = _name.find_last_of('['); + size_t close = _name.find_last_of(']'); + if (open != std::string::npos && close == _name.length() - 1) + { + subscript = atoi(_name.substr(open + 1).c_str()); + _name.erase(open); + } + + unsigned int numUniforms = mUniformIndex.size(); + for (unsigned int location = 0; location < numUniforms; location++) + { + if (mUniformIndex[location].name == _name && + 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 || + targetUniform->type == GL_SAMPLER_2D || + targetUniform->type == GL_SAMPLER_CUBE) + { + int arraySize = targetUniform->arraySize; + + if (arraySize == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + + count = std::min(arraySize - (int)mUniformIndex[location].element, count); + + memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint), + v, sizeof(GLint) * count); + } + else if (targetUniform->type == GL_BOOL) + { + int arraySize = targetUniform->arraySize; + + if (arraySize == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + + count = std::min(arraySize - (int)mUniformIndex[location].element, count); + GLboolean *boolParams = 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; + } +} + +// 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_SAMPLER_2D: + case GL_SAMPLER_CUBE: + 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 +ID3D10Blob *Program::compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable) +{ + if (!hlsl) + { + return NULL; + } + + DWORD result; + UINT flags = 0; + std::string sourceText; + if (perfActive()) + { + flags |= D3DCOMPILE_DEBUG; +#ifdef NDEBUG + flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL; +#else + flags |= D3DCOMPILE_SKIP_OPTIMIZATION; +#endif + + std::string sourcePath = getTempPath(); + sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl); + writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); + } + else + { + flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL; + sourceText = hlsl; + } + + ID3D10Blob *binary = NULL; + ID3D10Blob *errorMessage = NULL; + result = D3DCompile(hlsl, strlen(hlsl), NULL, NULL, NULL, "main", profile, flags, 0, &binary, &errorMessage); + + if (errorMessage) + { + const char *message = (const char*)errorMessage->GetBufferPointer(); + + appendToInfoLogSanitized(message); + TRACE("\n%s", hlsl); + TRACE("\n%s", message); + + errorMessage->Release(); + errorMessage = NULL; + } + + + if (FAILED(result)) + { + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) + { + error(GL_OUT_OF_MEMORY); + } + + return NULL; + } + + result = D3DXGetShaderConstantTable(static_cast<const DWORD*>(binary->GetBufferPointer()), constantTable); + + if (FAILED(result)) + { + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) + { + error(GL_OUT_OF_MEMORY); + } + + binary->Release(); + + return NULL; + } + + return binary; +} + +// 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]) +{ + Context *context = getContext(); + const int maxVaryingVectors = context->getMaximumVaryingVectors(); + + 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 <= maxVaryingVectors - n && !success; r++) + { + bool available = true; + + for (int y = 0; y < n && available; y++) + { + for (int x = 0; x < m && available; x++) + { + if (packing[r + y][x]) + { + available = false; + } + } + } + + if (available) + { + varying->reg = r; + varying->col = 0; + + for (int y = 0; y < n; y++) + { + for (int x = 0; x < m; x++) + { + packing[r + y][x] = &*varying; + } + } + + success = true; + } + } + + if (!success && m == 2) + { + for (int r = maxVaryingVectors - n; r >= 0 && !success; r--) + { + bool available = true; + + for (int y = 0; y < n && available; y++) + { + for (int x = 2; x < 4 && available; x++) + { + if (packing[r + y][x]) + { + available = false; + } + } + } + + if (available) + { + varying->reg = r; + varying->col = 2; + + for (int y = 0; y < n; y++) + { + for (int x = 2; x < 4; x++) + { + packing[r + y][x] = &*varying; + } + } + + success = true; + } + } + } + } + else if (m == 1) + { + int space[4] = {0}; + + for (int y = 0; y < maxVaryingVectors; y++) + { + for (int x = 0; x < 4; x++) + { + space[x] += packing[y][x] ? 0 : 1; + } + } + + int column = 0; + + for (int x = 0; x < 4; x++) + { + if (space[x] >= n && space[x] < space[column]) + { + column = x; + } + } + + if (space[column] >= n) + { + for (int r = 0; r < maxVaryingVectors; r++) + { + if (!packing[r][column]) + { + varying->reg = r; + + for (int y = r; y < r + n; y++) + { + packing[y][column] = &*varying; + } + + break; + } + } + + varying->col = column; + + success = true; + } + } + else UNREACHABLE(); + + if (!success) + { + 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 < maxVaryingVectors; 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; + } + + // Reset the varying register assignments + for (VaryingList::iterator fragVar = mFragmentShader->varyings.begin(); fragVar != mFragmentShader->varyings.end(); fragVar++) + { + fragVar->reg = -1; + fragVar->col = -1; + } + + for (VaryingList::iterator vtxVar = mVertexShader->varyings.begin(); vtxVar != mVertexShader->varyings.end(); vtxVar++) + { + vtxVar->reg = -1; + vtxVar->col = -1; + } + + // Map the varyings to the register file + const Varying *packing[MAX_VARYING_VECTORS_SM3][4] = {NULL}; + int registers = packVaryings(packing); + + if (registers < 0) + { + return false; + } + + // Write the HLSL input/output declarations + Context *context = getContext(); + const bool sm3 = context->supportsShaderModel3(); + const int maxVaryingVectors = context->getMaximumVaryingVectors(); + + if (registers == maxVaryingVectors && 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 %s does not match any vertex varying", input->name.c_str()); + + return false; + } + } + + 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 (sm3) { + mPixelHLSL += " float2 dx_VPos : VPOS;\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"; + if (sm3) { + mPixelHLSL += " gl_FragCoord.x = input.dx_VPos.x + 0.5;\n" + " gl_FragCoord.y = 2.0 * dx_Viewport.y - input.dx_VPos.y - 0.5;\n"; + } else { + mPixelHLSL += " 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"; + } + mPixelHLSL += " 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 = input.gl_PointCoord;\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"; + + 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"; + + ID3D10Blob *vertexBinary = compileToBinary(mVertexHLSL.c_str(), vertexProfile, &mConstantTableVS); + ID3D10Blob *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 + mDxDepthRangeLocation = getUniformLocation("dx_DepthRange", 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); + HRESULT result = constantTable->GetConstantDesc(constantHandle, &constantDescription, &descriptionCount); + ASSERT(SUCCEEDED(result)); + + 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) + { + for (unsigned int samplerIndex = constantDescription.RegisterIndex; samplerIndex < constantDescription.RegisterIndex + constantDescription.RegisterCount; samplerIndex++) + { + if (mConstantTablePS->GetConstantByName(NULL, constantDescription.Name) != NULL) + { + if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS) + { + mSamplersPS[samplerIndex].active = true; + mSamplersPS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D; + mSamplersPS[samplerIndex].logicalTextureUnit = 0; + } + else + { + appendToInfoLog("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS); + return false; + } + } + + if (mConstantTableVS->GetConstantByName(NULL, constantDescription.Name) != NULL) + { + if (samplerIndex < getContext()->getMaximumVertexTextureImageUnits()) + { + mSamplersVS[samplerIndex].active = true; + mSamplersVS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D; + mSamplersVS[samplerIndex].logicalTextureUnit = 0; + } + else + { + appendToInfoLog("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", getContext()->getMaximumVertexTextureImageUnits()); + return false; + } + } + } + } + + switch(constantDescription.Class) + { + case D3DXPC_STRUCT: + { + for (unsigned int arrayIndex = 0; arrayIndex < constantDescription.Elements; arrayIndex++) + { + for (unsigned int field = 0; field < constantDescription.StructMembers; field++) + { + D3DXHANDLE fieldHandle = mConstantTablePS->GetConstant(constantHandle, field); + + D3DXCONSTANT_DESC fieldDescription; + UINT descriptionCount = 1; + + HRESULT result = mConstantTablePS->GetConstantDesc(fieldHandle, &fieldDescription, &descriptionCount); + ASSERT(SUCCEEDED(result)); + + std::string structIndex = (constantDescription.Elements > 1) ? ("[" + str(arrayIndex) + "]") : ""; + + if (!defineUniform(fieldHandle, fieldDescription, name + constantDescription.Name + structIndex + ".")) + { + 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: + switch (constantDescription.Columns) + { + case 1: return new Uniform(GL_SAMPLER_2D, name, constantDescription.Elements); + default: UNREACHABLE(); + } + break; + case D3DXPT_SAMPLERCUBE: + switch (constantDescription.Columns) + { + case 1: return new Uniform(GL_SAMPLER_CUBE, 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); + ASSERT(SUCCEEDED(result)); + + if (constantDescription.RegisterSet == D3DXRS_SAMPLER) + { + unsigned int firstIndex = mConstantTablePS->GetSamplerIndex(constantPS); + + for (int i = 0; i < count; i++) + { + unsigned int samplerIndex = firstIndex + i; + + if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS) + { + ASSERT(mSamplersPS[samplerIndex].active); + mSamplersPS[samplerIndex].logicalTextureUnit = v[i]; + } + } + } + else + { + mConstantTablePS->SetIntArray(device, constantPS, v, count); + } + } + + if (constantVS) + { + D3DXCONSTANT_DESC constantDescription; + UINT descriptionCount = 1; + HRESULT result = mConstantTableVS->GetConstantDesc(constantVS, &constantDescription, &descriptionCount); + ASSERT(SUCCEEDED(result)); + + if (constantDescription.RegisterSet == D3DXRS_SAMPLER) + { + unsigned int firstIndex = mConstantTableVS->GetSamplerIndex(constantVS); + + for (int i = 0; i < count; i++) + { + unsigned int samplerIndex = firstIndex + i; + + if (samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF) + { + ASSERT(mSamplersVS[samplerIndex].active); + mSamplersVS[samplerIndex].logicalTextureUnit = v[i]; + } + } + } + else + { + 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; +} + + +// append a santized message to the program info log. +// The D3D compiler includes the current working directory +// in some of the warning or error messages, so lets remove +// any occurrances of those that we find in the log. +void Program::appendToInfoLogSanitized(const char *message) +{ + std::string msg(message); + CHAR path[MAX_PATH] = ""; + size_t len; + + len = GetCurrentDirectoryA(MAX_PATH, path); + if (len > 0 && len < MAX_PATH) + { + size_t found; + do { + found = msg.find(path); + if (found != std::string::npos) + { + // the +1 here is intentional so that we remove + // the trailing '\' that occurs after the path + msg.erase(found, len+1); + } + } while (found != std::string::npos); + } + + appendToInfoLog("%s\n", msg.c_str()); +} + +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; + mInfoLog = NULL; + } +} + +// 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++) + { + mSamplersPS[index].active = false; + } + + for (int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; index++) + { + mSamplersVS[index].active = false; + } + + while (!mUniforms.empty()) + { + delete mUniforms.back(); + mUniforms.pop_back(); + } + + mDxDepthRangeLocation = -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) +{ + // Skip over inactive attributes + unsigned int activeAttribute = 0; + unsigned int attribute; + for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++) + { + if (mLinkedAttribute[attribute].name.empty()) + { + continue; + } + + if (activeAttribute == index) + { + break; + } + + activeAttribute++; + } + + if (bufsize > 0) + { + const char *string = mLinkedAttribute[attribute].name.c_str(); + + strncpy(name, string, bufsize); + name[bufsize - 1] = '\0'; + + if (length) + { + *length = strlen(name); + } + } + + *size = 1; // Always a single 'type' instance + + *type = mLinkedAttribute[attribute].type; +} + +GLint 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) +{ + // Skip over internal uniforms + unsigned int activeUniform = 0; + unsigned int uniform; + for (uniform = 0; uniform < mUniforms.size(); uniform++) + { + if (mUniforms[uniform]->name.substr(0, 3) == "dx_") + { + continue; + } + + if (activeUniform == index) + { + break; + } + + activeUniform++; + } + + ASSERT(uniform < mUniforms.size()); // index must be smaller than getActiveUniformCount() + + 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_") + { + int length = (int)(undecorate(mUniforms[uniformIndex]->name).length() + 1); + if (mUniforms[uniformIndex]->arraySize != 1) + { + length += 3; // Counting in "[0]". + } + maxLength = std::max(length, 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(true)) + { + mValidated = false; + } + else + { + mValidated = true; + } + } +} + +bool Program::validateSamplers(bool logErrors) +{ + // if any two active samplers in a program are of different types, but refer to the same + // texture image unit, and this is the current program, then ValidateProgram will fail, and + // DrawArrays and DrawElements will issue the INVALID_OPERATION error. + + const unsigned int maxCombinedTextureImageUnits = getContext()->getMaximumCombinedTextureImageUnits(); + TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF]; + + for (unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; ++i) + { + textureUnitType[i] = TEXTURE_UNKNOWN; + } + + for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) + { + if (mSamplersPS[i].active) + { + unsigned int unit = mSamplersPS[i].logicalTextureUnit; + + if (unit >= maxCombinedTextureImageUnits) + { + if (logErrors) + { + appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); + } + + return false; + } + + if (textureUnitType[unit] != TEXTURE_UNKNOWN) + { + if (mSamplersPS[i].textureType != textureUnitType[unit]) + { + if (logErrors) + { + appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit); + } + + return false; + } + } + else + { + textureUnitType[unit] = mSamplersPS[i].textureType; + } + } + } + + for (unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; ++i) + { + if (mSamplersVS[i].active) + { + unsigned int unit = mSamplersVS[i].logicalTextureUnit; + + if (unit >= maxCombinedTextureImageUnits) + { + if (logErrors) + { + appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); + } + + return false; + } + + if (textureUnitType[unit] != TEXTURE_UNKNOWN) + { + if (mSamplersVS[i].textureType != textureUnitType[unit]) + { + if (logErrors) + { + appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit); + } + + return false; + } + } + else + { + textureUnitType[unit] = mSamplersVS[i].textureType; + } + } + } + + 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::getDxDepthRangeLocation() const +{ + return mDxDepthRangeLocation; +} + +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 000000000..8085522eb --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Program.h @@ -0,0 +1,226 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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 <d3dcompiler.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); + + GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex); + TextureType getSamplerTextureType(SamplerType type, unsigned int samplerIndex); + + 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 getDxDepthRangeLocation() 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(bool logErrors); + bool isValidated() const; + + unsigned int getSerial() const; + + private: + DISALLOW_COPY_AND_ASSIGN(Program); + + ID3D10Blob *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 appendToInfoLogSanitized(const char *message); + 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; + TextureType textureType; + }; + + Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS]; + Sampler mSamplersVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF]; + + typedef std::vector<Uniform*> UniformArray; + UniformArray mUniforms; + typedef std::vector<UniformLocation> UniformIndex; + UniformIndex mUniformIndex; + + GLint mDxDepthRangeLocation; + 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; + + const 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 000000000..2de1e718d --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/RefCountObject.cpp @@ -0,0 +1,52 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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() +{ + ASSERT(mRefCount == 0); +} + +void RefCountObject::addRef() const +{ + mRefCount++; +} + +void RefCountObject::release() const +{ + ASSERT(mRefCount > 0); + + if (--mRefCount == 0) + { + delete this; + } +} + +void RefCountObjectBindingPointer::set(RefCountObject *newObject) +{ + // addRef first in case newObject == mObject and this is the last reference to it. + if (newObject != NULL) newObject->addRef(); + if (mObject != NULL) mObject->release(); + + mObject = newObject; +} + +} diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/RefCountObject.h b/Source/ThirdParty/ANGLE/src/libGLESv2/RefCountObject.h new file mode 100644 index 000000000..a1493505f --- /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 000000000..ace8d7b90 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.cpp @@ -0,0 +1,512 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderbuffer.cpp: the gl::Renderbuffer class and its derived classes +// Colorbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer +// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. + +#include "libGLESv2/Renderbuffer.h" + +#include "libGLESv2/main.h" +#include "libGLESv2/Texture.h" +#include "libGLESv2/utilities.h" + +namespace gl +{ +unsigned int RenderbufferStorage::mCurrentSerial = 1; + +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(); +} + +GLsizei Renderbuffer::getWidth() const +{ + return mStorage->getWidth(); +} + +GLsizei Renderbuffer::getHeight() const +{ + return mStorage->getHeight(); +} + +GLenum Renderbuffer::getInternalFormat() const +{ + return mStorage->getInternalFormat(); +} + +GLuint Renderbuffer::getRedSize() const +{ + return mStorage->getRedSize(); +} + +GLuint Renderbuffer::getGreenSize() const +{ + return mStorage->getGreenSize(); +} + +GLuint Renderbuffer::getBlueSize() const +{ + return mStorage->getBlueSize(); +} + +GLuint Renderbuffer::getAlphaSize() const +{ + return mStorage->getAlphaSize(); +} + +GLuint Renderbuffer::getDepthSize() const +{ + return mStorage->getDepthSize(); +} + +GLuint Renderbuffer::getStencilSize() const +{ + return mStorage->getStencilSize(); +} + +GLsizei Renderbuffer::getSamples() const +{ + return mStorage->getSamples(); +} + +unsigned int Renderbuffer::getSerial() const +{ + return mStorage->getSerial(); +} + +void Renderbuffer::setStorage(RenderbufferStorage *newStorage) +{ + ASSERT(newStorage != NULL); + + delete mStorage; + mStorage = newStorage; +} + +RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerial()) +{ + mWidth = 0; + mHeight = 0; + mInternalFormat = GL_RGBA4; + mD3DFormat = D3DFMT_A8R8G8B8; + mSamples = 0; +} + +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; +} + +GLsizei RenderbufferStorage::getWidth() const +{ + return mWidth; +} + +GLsizei RenderbufferStorage::getHeight() const +{ + return mHeight; +} + +GLenum RenderbufferStorage::getInternalFormat() const +{ + return mInternalFormat; +} + +GLuint RenderbufferStorage::getRedSize() const +{ + return dx2es::GetRedSize(getD3DFormat()); +} + +GLuint RenderbufferStorage::getGreenSize() const +{ + return dx2es::GetGreenSize(getD3DFormat()); +} + +GLuint RenderbufferStorage::getBlueSize() const +{ + return dx2es::GetBlueSize(getD3DFormat()); +} + +GLuint RenderbufferStorage::getAlphaSize() const +{ + return dx2es::GetAlphaSize(getD3DFormat()); +} + +GLuint RenderbufferStorage::getDepthSize() const +{ + return dx2es::GetDepthSize(getD3DFormat()); +} + +GLuint RenderbufferStorage::getStencilSize() const +{ + return dx2es::GetStencilSize(getD3DFormat()); +} + +GLsizei RenderbufferStorage::getSamples() const +{ + return mSamples; +} + +D3DFORMAT RenderbufferStorage::getD3DFormat() const +{ + return mD3DFormat; +} + +unsigned int RenderbufferStorage::getSerial() const +{ + return mSerial; +} + +unsigned int RenderbufferStorage::issueSerial() +{ + return mCurrentSerial++; +} + +Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget), mTexture(NULL) +{ + if (renderTarget) + { + renderTarget->AddRef(); + + D3DSURFACE_DESC description; + renderTarget->GetDesc(&description); + + mWidth = description.Width; + mHeight = description.Height; + mInternalFormat = dx2es::ConvertBackBufferFormat(description.Format); + mD3DFormat = description.Format; + mSamples = dx2es::GetSamplesFromMultisampleType(description.MultiSampleType); + } +} + +Colorbuffer::Colorbuffer(Texture *texture, GLenum target) : mRenderTarget(NULL), mTexture(texture), mTarget(target) +{ + if (texture) + { + mWidth = texture->getWidth(); + mHeight = texture->getHeight(); + mInternalFormat = texture->getInternalFormat(); + mD3DFormat = texture->getD3DFormat(); + mSamples = 0; + + mRenderTarget = texture->getRenderTarget(target); + } +} + +Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL), mTexture(NULL) +{ + IDirect3DDevice9 *device = getDevice(); + + D3DFORMAT requestedFormat = es2dx::ConvertRenderbufferFormat(format); + int supportedSamples = getContext()->getNearestSupportedSamples(requestedFormat, samples); + + if (supportedSamples == -1) + { + error(GL_OUT_OF_MEMORY); + + return; + } + + if (width > 0 && height > 0) + { + HRESULT result = device->CreateRenderTarget(width, height, requestedFormat, + es2dx::GetMultisampleTypeFromSamples(supportedSamples), 0, FALSE, &mRenderTarget, NULL); + + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) + { + error(GL_OUT_OF_MEMORY); + + return; + } + + ASSERT(SUCCEEDED(result)); + } + + mWidth = width; + mHeight = height; + mInternalFormat = format; + mD3DFormat = requestedFormat; + mSamples = supportedSamples; +} + +Colorbuffer::~Colorbuffer() +{ + if (mRenderTarget) + { + mRenderTarget->Release(); + } +} + +GLsizei Colorbuffer::getWidth() const +{ + if (mTexture) + { + return mTexture->getWidth(); + } + + return mWidth; +} + +GLsizei Colorbuffer::getHeight() const +{ + if (mTexture) + { + return mTexture->getHeight(); + } + + return mHeight; +} + +GLenum Colorbuffer::getInternalFormat() const +{ + if (mTexture) + { + return mTexture->getInternalFormat(); + } + + return mInternalFormat; +} + +GLenum Colorbuffer::getType() const +{ + if (mTexture) + { + return mTexture->getType(); + } + + return GL_UNSIGNED_BYTE; +} + +D3DFORMAT Colorbuffer::getD3DFormat() const +{ + if (mTexture) + { + return mTexture->getD3DFormat(); + } + + return mD3DFormat; +} + +bool Colorbuffer::isColorbuffer() const +{ + return true; +} + +IDirect3DSurface9 *Colorbuffer::getRenderTarget() +{ + if (mTexture) + { + if (mRenderTarget) + { + mRenderTarget->Release(); + } + + mRenderTarget = mTexture->getRenderTarget(mTarget); + } + + return mRenderTarget; +} + +DepthStencilbuffer::DepthStencilbuffer(IDirect3DSurface9 *depthStencil) : mDepthStencil(depthStencil) +{ + if (depthStencil) + { + depthStencil->AddRef(); + + D3DSURFACE_DESC description; + depthStencil->GetDesc(&description); + + mWidth = description.Width; + mHeight = description.Height; + mInternalFormat = dx2es::ConvertDepthStencilFormat(description.Format); + mSamples = dx2es::GetSamplesFromMultisampleType(description.MultiSampleType); + mD3DFormat = description.Format; + } +} + +DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples) +{ + IDirect3DDevice9 *device = getDevice(); + + mDepthStencil = NULL; + + int supportedSamples = getContext()->getNearestSupportedSamples(D3DFMT_D24S8, samples); + + if (supportedSamples == -1) + { + error(GL_OUT_OF_MEMORY); + + return; + } + + if (width > 0 && height > 0) + { + HRESULT result = device->CreateDepthStencilSurface(width, height, D3DFMT_D24S8, es2dx::GetMultisampleTypeFromSamples(supportedSamples), + 0, FALSE, &mDepthStencil, 0); + + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) + { + error(GL_OUT_OF_MEMORY); + + return; + } + + ASSERT(SUCCEEDED(result)); + } + + mWidth = width; + mHeight = height; + mInternalFormat = GL_DEPTH24_STENCIL8_OES; + mD3DFormat = D3DFMT_D24S8; + mSamples = supportedSamples; +} + +DepthStencilbuffer::~DepthStencilbuffer() +{ + if (mDepthStencil) + { + mDepthStencil->Release(); + } +} + +bool DepthStencilbuffer::isDepthbuffer() const +{ + return true; +} + +bool DepthStencilbuffer::isStencilbuffer() const +{ + return true; +} + +IDirect3DSurface9 *DepthStencilbuffer::getDepthStencil() +{ + return mDepthStencil; +} + +Depthbuffer::Depthbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil) +{ + if (depthStencil) + { + mInternalFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function + // will expect one of the valid renderbuffer formats for use in + // glRenderbufferStorage + } +} + +Depthbuffer::Depthbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples) +{ + if (getDepthStencil()) + { + mInternalFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function + // will expect one of the valid renderbuffer formats for use in + // glRenderbufferStorage + } +} + +Depthbuffer::~Depthbuffer() +{ +} + +bool Depthbuffer::isDepthbuffer() const +{ + return true; +} + +bool Depthbuffer::isStencilbuffer() const +{ + return false; +} + +Stencilbuffer::Stencilbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil) +{ + if (depthStencil) + { + mInternalFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function + // will expect one of the valid renderbuffer formats for use in + // glRenderbufferStorage + } +} + +Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples) +{ + if (getDepthStencil()) + { + mInternalFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function + // will expect one of the valid renderbuffer formats for use in + // glRenderbufferStorage + } +} + +Stencilbuffer::~Stencilbuffer() +{ +} + +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 000000000..5cf829c70 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.h @@ -0,0 +1,192 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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 +{ +class Texture; + +// 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 GLsizei getWidth() const; + virtual GLsizei getHeight() const; + virtual GLenum getInternalFormat() const; + GLuint getRedSize() const; + GLuint getGreenSize() const; + GLuint getBlueSize() const; + GLuint getAlphaSize() const; + GLuint getDepthSize() const; + GLuint getStencilSize() const; + virtual GLsizei getSamples() const; + + virtual D3DFORMAT getD3DFormat() const; + + unsigned int getSerial() const; + + protected: + GLsizei mWidth; + GLsizei mHeight; + GLenum mInternalFormat; + D3DFORMAT mD3DFormat; + GLsizei mSamples; + + private: + DISALLOW_COPY_AND_ASSIGN(RenderbufferStorage); + + static unsigned int issueSerial(); + + const unsigned int mSerial; + + static unsigned int mCurrentSerial; +}; + +// Renderbuffer implements the GL renderbuffer object. +// It's only a proxy for a RenderbufferStorage instance; 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(); + + GLsizei getWidth() const; + GLsizei getHeight() const; + GLenum getInternalFormat() const; + D3DFORMAT getD3DFormat() const; + GLuint getRedSize() const; + GLuint getGreenSize() const; + GLuint getBlueSize() const; + GLuint getAlphaSize() const; + GLuint getDepthSize() const; + GLuint getStencilSize() const; + GLsizei getSamples() const; + + unsigned int getSerial() const; + + void setStorage(RenderbufferStorage *newStorage); + RenderbufferStorage *getStorage() { return mStorage; } + + private: + DISALLOW_COPY_AND_ASSIGN(Renderbuffer); + + RenderbufferStorage *mStorage; +}; + +class Colorbuffer : public RenderbufferStorage +{ + public: + explicit Colorbuffer(IDirect3DSurface9 *renderTarget); + Colorbuffer(Texture *texture, GLenum target); + Colorbuffer(GLsizei width, GLsizei height, GLenum format, GLsizei samples); + + virtual ~Colorbuffer(); + + virtual bool isColorbuffer() const; + + virtual IDirect3DSurface9 *getRenderTarget(); + + virtual GLsizei getWidth() const; + virtual GLsizei getHeight() const; + virtual GLenum getInternalFormat() const; + virtual GLenum getType() const; + + virtual D3DFORMAT getD3DFormat() const; + + private: + DISALLOW_COPY_AND_ASSIGN(Colorbuffer); + + IDirect3DSurface9 *mRenderTarget; + Texture *mTexture; + GLenum mTarget; +}; + +class DepthStencilbuffer : public RenderbufferStorage +{ + public: + explicit DepthStencilbuffer(IDirect3DSurface9 *depthStencil); + DepthStencilbuffer(GLsizei width, GLsizei height, GLsizei samples); + + ~DepthStencilbuffer(); + + virtual bool isDepthbuffer() const; + virtual bool isStencilbuffer() const; + + virtual IDirect3DSurface9 *getDepthStencil(); + + private: + DISALLOW_COPY_AND_ASSIGN(DepthStencilbuffer); + IDirect3DSurface9 *mDepthStencil; +}; + +class Depthbuffer : public DepthStencilbuffer +{ + public: + explicit Depthbuffer(IDirect3DSurface9 *depthStencil); + Depthbuffer(GLsizei width, GLsizei height, GLsizei samples); + + virtual ~Depthbuffer(); + + virtual bool isDepthbuffer() const; + virtual bool isStencilbuffer() const; + + private: + DISALLOW_COPY_AND_ASSIGN(Depthbuffer); +}; + +class Stencilbuffer : public DepthStencilbuffer +{ + public: + explicit Stencilbuffer(IDirect3DSurface9 *depthStencil); + Stencilbuffer(GLsizei width, GLsizei height, GLsizei samples); + + virtual ~Stencilbuffer(); + + virtual bool isDepthbuffer() const; + virtual 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 000000000..ae26352e0 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.cpp @@ -0,0 +1,320 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ResourceManager.cpp: Implements the gl::ResourceManager class, which tracks and +// retrieves objects which may be shared by multiple Contexts. + +#include "libGLESv2/ResourceManager.h" + +#include "libGLESv2/Buffer.h" +#include "libGLESv2/Program.h" +#include "libGLESv2/RenderBuffer.h" +#include "libGLESv2/Shader.h" +#include "libGLESv2/Texture.h" + +namespace gl +{ +ResourceManager::ResourceManager() +{ + mRefCount = 1; +} + +ResourceManager::~ResourceManager() +{ + while (!mBufferMap.empty()) + { + deleteBuffer(mBufferMap.begin()->first); + } + + while (!mProgramMap.empty()) + { + deleteProgram(mProgramMap.begin()->first); + } + + while (!mShaderMap.empty()) + { + deleteShader(mShaderMap.begin()->first); + } + + while (!mRenderbufferMap.empty()) + { + deleteRenderbuffer(mRenderbufferMap.begin()->first); + } + + while (!mTextureMap.empty()) + { + deleteTexture(mTextureMap.begin()->first); + } +} + +void ResourceManager::addRef() +{ + mRefCount++; +} + +void ResourceManager::release() +{ + if (--mRefCount == 0) + { + delete this; + } +} + +// Returns an unused buffer name +GLuint ResourceManager::createBuffer() +{ + GLuint handle = mBufferHandleAllocator.allocate(); + + mBufferMap[handle] = NULL; + + return handle; +} + +// Returns an unused shader/program name +GLuint ResourceManager::createShader(GLenum type) +{ + GLuint handle = mProgramShaderHandleAllocator.allocate(); + + if (type == GL_VERTEX_SHADER) + { + mShaderMap[handle] = new VertexShader(this, handle); + } + else if (type == GL_FRAGMENT_SHADER) + { + mShaderMap[handle] = new FragmentShader(this, handle); + } + else UNREACHABLE(); + + return handle; +} + +// Returns an unused program/shader name +GLuint ResourceManager::createProgram() +{ + GLuint handle = mProgramShaderHandleAllocator.allocate(); + + mProgramMap[handle] = new Program(this, handle); + + return handle; +} + +// Returns an unused texture name +GLuint ResourceManager::createTexture() +{ + GLuint handle = mTextureHandleAllocator.allocate(); + + mTextureMap[handle] = NULL; + + return handle; +} + +// Returns an unused renderbuffer name +GLuint ResourceManager::createRenderbuffer() +{ + GLuint handle = mRenderbufferHandleAllocator.allocate(); + + mRenderbufferMap[handle] = NULL; + + return handle; +} + +void ResourceManager::deleteBuffer(GLuint buffer) +{ + BufferMap::iterator bufferObject = mBufferMap.find(buffer); + + if (bufferObject != mBufferMap.end()) + { + mBufferHandleAllocator.release(bufferObject->first); + if (bufferObject->second) bufferObject->second->release(); + mBufferMap.erase(bufferObject); + } +} + +void ResourceManager::deleteShader(GLuint shader) +{ + ShaderMap::iterator shaderObject = mShaderMap.find(shader); + + if (shaderObject != mShaderMap.end()) + { + if (shaderObject->second->getRefCount() == 0) + { + mProgramShaderHandleAllocator.release(shaderObject->first); + delete shaderObject->second; + mShaderMap.erase(shaderObject); + } + else + { + shaderObject->second->flagForDeletion(); + } + } +} + +void ResourceManager::deleteProgram(GLuint program) +{ + ProgramMap::iterator programObject = mProgramMap.find(program); + + if (programObject != mProgramMap.end()) + { + if (programObject->second->getRefCount() == 0) + { + mProgramShaderHandleAllocator.release(programObject->first); + delete programObject->second; + mProgramMap.erase(programObject); + } + else + { + programObject->second->flagForDeletion(); + } + } +} + +void ResourceManager::deleteTexture(GLuint texture) +{ + TextureMap::iterator textureObject = mTextureMap.find(texture); + + if (textureObject != mTextureMap.end()) + { + mTextureHandleAllocator.release(textureObject->first); + if (textureObject->second) textureObject->second->release(); + mTextureMap.erase(textureObject); + } +} + +void ResourceManager::deleteRenderbuffer(GLuint renderbuffer) +{ + RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer); + + if (renderbufferObject != mRenderbufferMap.end()) + { + mRenderbufferHandleAllocator.release(renderbufferObject->first); + if (renderbufferObject->second) renderbufferObject->second->release(); + mRenderbufferMap.erase(renderbufferObject); + } +} + +Buffer *ResourceManager::getBuffer(unsigned int handle) +{ + BufferMap::iterator buffer = mBufferMap.find(handle); + + if (buffer == mBufferMap.end()) + { + return NULL; + } + else + { + return buffer->second; + } +} + +Shader *ResourceManager::getShader(unsigned int handle) +{ + ShaderMap::iterator shader = mShaderMap.find(handle); + + if (shader == mShaderMap.end()) + { + return NULL; + } + else + { + return shader->second; + } +} + +Texture *ResourceManager::getTexture(unsigned int handle) +{ + if (handle == 0) return NULL; + + TextureMap::iterator texture = mTextureMap.find(handle); + + if (texture == mTextureMap.end()) + { + return NULL; + } + else + { + return texture->second; + } +} + +Program *ResourceManager::getProgram(unsigned int handle) +{ + ProgramMap::iterator program = mProgramMap.find(handle); + + if (program == mProgramMap.end()) + { + return NULL; + } + else + { + return program->second; + } +} + +Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle) +{ + RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle); + + if (renderbuffer == mRenderbufferMap.end()) + { + return NULL; + } + else + { + return renderbuffer->second; + } +} + +void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer) +{ + mRenderbufferMap[handle] = buffer; +} + +void ResourceManager::checkBufferAllocation(unsigned int buffer) +{ + if (buffer != 0 && !getBuffer(buffer)) + { + Buffer *bufferObject = new Buffer(buffer); + mBufferMap[buffer] = bufferObject; + bufferObject->addRef(); + } +} + +void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type) +{ + if (!getTexture(texture) && texture != 0) + { + Texture *textureObject; + + if (type == TEXTURE_2D) + { + textureObject = new Texture2D(texture); + } + else if (type == TEXTURE_CUBE) + { + textureObject = new TextureCubeMap(texture); + } + else + { + UNREACHABLE(); + return; + } + + mTextureMap[texture] = textureObject; + textureObject->addRef(); + } +} + +void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer) +{ + if (renderbuffer != 0 && !getRenderbuffer(renderbuffer)) + { + Renderbuffer *renderbufferObject = new Renderbuffer(renderbuffer, new Colorbuffer(0, 0, GL_RGBA4, 0)); + mRenderbufferMap[renderbuffer] = renderbufferObject; + renderbufferObject->addRef(); + } +} + +} diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.h b/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.h new file mode 100644 index 000000000..5185fc9db --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.h @@ -0,0 +1,104 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// 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 <hash_map> + +#include "common/angleutils.h" +#include "libGLESv2/HandleAllocator.h" + +namespace gl +{ +class Buffer; +class Shader; +class Program; +class Texture; +class Renderbuffer; + +enum TextureType +{ + TEXTURE_2D, + TEXTURE_CUBE, + + TEXTURE_TYPE_COUNT, + TEXTURE_UNKNOWN +}; + +enum SamplerType +{ + SAMPLER_PIXEL, + SAMPLER_VERTEX +}; + +class ResourceManager +{ + public: + ResourceManager(); + ~ResourceManager(); + + void addRef(); + void release(); + + GLuint createBuffer(); + GLuint createShader(GLenum type); + GLuint createProgram(); + GLuint createTexture(); + GLuint createRenderbuffer(); + + void deleteBuffer(GLuint buffer); + void deleteShader(GLuint shader); + void deleteProgram(GLuint program); + void deleteTexture(GLuint texture); + void deleteRenderbuffer(GLuint renderbuffer); + + Buffer *getBuffer(GLuint handle); + Shader *getShader(GLuint handle); + Program *getProgram(GLuint handle); + Texture *getTexture(GLuint handle); + Renderbuffer *getRenderbuffer(GLuint handle); + + void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer); + + void checkBufferAllocation(unsigned int buffer); + void checkTextureAllocation(GLuint texture, TextureType type); + void checkRenderbufferAllocation(GLuint renderbuffer); + + private: + DISALLOW_COPY_AND_ASSIGN(ResourceManager); + + std::size_t mRefCount; + + typedef stdext::hash_map<GLuint, Buffer*> BufferMap; + BufferMap mBufferMap; + HandleAllocator mBufferHandleAllocator; + + typedef stdext::hash_map<GLuint, Shader*> ShaderMap; + ShaderMap mShaderMap; + + typedef stdext::hash_map<GLuint, Program*> ProgramMap; + ProgramMap mProgramMap; + HandleAllocator mProgramShaderHandleAllocator; + + typedef stdext::hash_map<GLuint, Texture*> TextureMap; + TextureMap mTextureMap; + HandleAllocator mTextureHandleAllocator; + + typedef stdext::hash_map<GLuint, Renderbuffer*> RenderbufferMap; + RenderbufferMap mRenderbufferMap; + HandleAllocator mRenderbufferHandleAllocator; +}; + +} + +#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 000000000..f66b2c52a --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.cpp @@ -0,0 +1,528 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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) + { + ShBuiltInResources resources; + ShInitBuiltInResources(&resources); + Context *context = getContext(); + + resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS; + resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS; + resources.MaxVaryingVectors = context->getMaximumVaryingVectors(); + resources.MaxVertexTextureImageUnits = context->getMaximumVertexTextureImageUnits(); + resources.MaxCombinedTextureImageUnits = context->getMaximumCombinedTextureImageUnits(); + resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; + resources.MaxFragmentUniformVectors = context->getMaximumFragmentUniformVectors(); + resources.MaxDrawBuffers = MAX_DRAW_BUFFERS; + resources.OES_standard_derivatives = 1; + + mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, SH_HLSL_OUTPUT, &resources); + mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, SH_HLSL_OUTPUT, &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 %255s %255s", 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; + } + + delete[] mInfoLog; + mInfoLog = NULL; + + int compileOptions = SH_OBJECT_CODE; + std::string sourcePath; + if (perfActive()) + { + sourcePath = getTempPath(); + writeFile(sourcePath.c_str(), mSource, strlen(mSource)); + compileOptions |= SH_LINE_DIRECTIVES; + } + + int result; + if (sourcePath.empty()) + { + result = ShCompile(compiler, &mSource, 1, compileOptions); + } + else + { + const char* sourceStrings[2] = + { + sourcePath.c_str(), + mSource + }; + + result = ShCompile(compiler, sourceStrings, 2, compileOptions | SH_SOURCE_PATH); + } + + if (result) + { + int objCodeLen = 0; + ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen); + mHlsl = new char[objCodeLen]; + ShGetObjectCode(compiler, mHlsl); + } + else + { + int infoLogLen = 0; + ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen); + mInfoLog = new char[infoLogLen]; + ShGetInfoLog(compiler, mInfoLog); + + TRACE("\n%s", mInfoLog); + } +} + +GLenum Shader::parseType(const std::string &type) +{ + if (type == "float") + { + return GL_FLOAT; + } + else if (type == "float2") + { + return GL_FLOAT_VEC2; + } + else if (type == "float3") + { + return GL_FLOAT_VEC3; + } + else if (type == "float4") + { + return GL_FLOAT_VEC4; + } + else if (type == "float2x2") + { + return GL_FLOAT_MAT2; + } + else if (type == "float3x3") + { + return GL_FLOAT_MAT3; + } + else if (type == "float4x4") + { + return GL_FLOAT_MAT4; + } + else UNREACHABLE(); + + return GL_NONE; +} + +// true if varying x has a higher priority in packing than y +bool Shader::compareVarying(const Varying &x, const Varying &y) +{ + if(x.type == y.type) + { + return x.size > y.size; + } + + switch (x.type) + { + case GL_FLOAT_MAT4: return true; + case GL_FLOAT_MAT2: + switch(y.type) + { + case GL_FLOAT_MAT4: return false; + case GL_FLOAT_MAT2: return true; + case GL_FLOAT_VEC4: return true; + case GL_FLOAT_MAT3: return true; + case GL_FLOAT_VEC3: return true; + case GL_FLOAT_VEC2: return true; + case GL_FLOAT: return true; + default: UNREACHABLE(); + } + break; + case GL_FLOAT_VEC4: + switch(y.type) + { + case GL_FLOAT_MAT4: return false; + case GL_FLOAT_MAT2: return false; + case GL_FLOAT_VEC4: return true; + case GL_FLOAT_MAT3: return true; + case GL_FLOAT_VEC3: return true; + case GL_FLOAT_VEC2: return true; + case GL_FLOAT: return true; + default: UNREACHABLE(); + } + break; + case GL_FLOAT_MAT3: + switch(y.type) + { + case GL_FLOAT_MAT4: return false; + case GL_FLOAT_MAT2: return false; + case GL_FLOAT_VEC4: return false; + case GL_FLOAT_MAT3: return true; + case GL_FLOAT_VEC3: return true; + case GL_FLOAT_VEC2: return true; + case GL_FLOAT: return true; + default: UNREACHABLE(); + } + break; + case GL_FLOAT_VEC3: + switch(y.type) + { + case GL_FLOAT_MAT4: return false; + case GL_FLOAT_MAT2: return false; + case GL_FLOAT_VEC4: return false; + case GL_FLOAT_MAT3: return false; + case GL_FLOAT_VEC3: return true; + case GL_FLOAT_VEC2: return true; + case GL_FLOAT: return true; + default: UNREACHABLE(); + } + break; + case GL_FLOAT_VEC2: + switch(y.type) + { + case GL_FLOAT_MAT4: return false; + case GL_FLOAT_MAT2: return false; + case GL_FLOAT_VEC4: return false; + case GL_FLOAT_MAT3: return false; + case GL_FLOAT_VEC3: return false; + case GL_FLOAT_VEC2: return true; + case GL_FLOAT: return true; + default: UNREACHABLE(); + } + break; + case GL_FLOAT: return false; + default: UNREACHABLE(); + } + + return false; +} + +VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle) +{ +} + +VertexShader::~VertexShader() +{ +} + +GLenum VertexShader::getType() +{ + return GL_VERTEX_SHADER; +} + +void VertexShader::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 %255s _%255s", attributeType, attributeName); + + if (matches != 2) + { + break; + } + + mAttributes.push_back(Attribute(parseType(attributeType), attributeName)); + + input = strstr(input, ";") + 2; + } + } +} + +FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle) +{ +} + +FragmentShader::~FragmentShader() +{ +} + +GLenum FragmentShader::getType() +{ + return GL_FRAGMENT_SHADER; +} + +void FragmentShader::compile() +{ + 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 000000000..535b42d8c --- /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(); + + virtual GLenum getType(); + virtual 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(); + + virtual GLenum getType(); + virtual 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 000000000..bb4c4b8f5 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp @@ -0,0 +1,2589 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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 <d3dx9tex.h> + +#include <algorithm> +#include <intrin.h> + +#include "common/debug.h" + +#include "libEGL/Display.h" + +#include "libGLESv2/main.h" +#include "libGLESv2/mathutil.h" +#include "libGLESv2/utilities.h" +#include "libGLESv2/Blit.h" +#include "libGLESv2/Framebuffer.h" + +namespace gl +{ +unsigned int Texture::mCurrentSerial = 1; + +Texture::Image::Image() + : width(0), height(0), dirty(false), surface(NULL), format(GL_NONE), type(GL_UNSIGNED_BYTE) +{ +} + +Texture::Image::~Image() +{ + if (surface) + { + surface->Release(); + } +} + +bool Texture::Image::isRenderable() const +{ + switch(getD3DFormat()) + { + case D3DFMT_L8: + case D3DFMT_A8L8: + case D3DFMT_DXT1: + return false; + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + case D3DFMT_A16B16G16R16F: + case D3DFMT_A32B32G32R32F: + return true; + default: + UNREACHABLE(); + } + + return false; +} + +D3DFORMAT Texture::Image::getD3DFormat() const +{ + if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || + format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) + { + return D3DFMT_DXT1; + } + else if (type == GL_FLOAT) + { + return D3DFMT_A32B32G32R32F; + } + else if (type == GL_HALF_FLOAT_OES) + { + return D3DFMT_A16B16G16R16F; + } + else if (type == GL_UNSIGNED_BYTE) + { + if (format == GL_LUMINANCE && getContext()->supportsLuminanceTextures()) + { + return D3DFMT_L8; + } + else if (format == GL_LUMINANCE_ALPHA && getContext()->supportsLuminanceAlphaTextures()) + { + return D3DFMT_A8L8; + } + else if (format == GL_RGB) + { + return D3DFMT_X8R8G8B8; + } + + return D3DFMT_A8R8G8B8; + } + + return D3DFMT_A8R8G8B8; +} + +Texture::Texture(GLuint id) : RefCountObject(id), mSerial(issueSerial()) +{ + mMinFilter = GL_NEAREST_MIPMAP_LINEAR; + mMagFilter = GL_LINEAR; + mWrapS = GL_REPEAT; + mWrapT = GL_REPEAT; + mDirtyParameter = true; + + mDirtyImage = true; + + mIsRenderable = false; +} + +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; + mDirtyParameter = 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; + mDirtyParameter = 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; + mDirtyParameter = 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; + mDirtyParameter = 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; +} + +// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input +// into the target 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, D3DSURFACE_DESC *description) const +{ + GLsizei inputPitch = -ComputePitch(width, format, type, unpackAlignment); + input = ((char*)input) - inputPitch * (height - 1); + + switch (type) + { + case GL_UNSIGNED_BYTE: + 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, description->Format == D3DFMT_L8); + break; + case GL_LUMINANCE_ALPHA: + loadLuminanceAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, description->Format == D3DFMT_A8L8); + break; + case GL_RGB: + loadRGBUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + break; + case GL_RGBA: + if (supportsSSE2()) + { + loadRGBAUByteImageDataSSE2(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + } + else + { + loadRGBAUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + } + break; + case GL_BGRA_EXT: + loadBGRAImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + break; + default: UNREACHABLE(); + } + break; + case GL_UNSIGNED_SHORT_5_6_5: + switch (format) + { + case GL_RGB: + loadRGB565ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + break; + default: UNREACHABLE(); + } + break; + case GL_UNSIGNED_SHORT_4_4_4_4: + switch (format) + { + case GL_RGBA: + loadRGBA4444ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + break; + default: UNREACHABLE(); + } + break; + case GL_UNSIGNED_SHORT_5_5_5_1: + switch (format) + { + case GL_RGBA: + loadRGBA5551ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + break; + default: UNREACHABLE(); + } + break; + case GL_FLOAT: + switch (format) + { + // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D + case GL_ALPHA: + loadAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + break; + case GL_LUMINANCE: + loadLuminanceFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + break; + case GL_LUMINANCE_ALPHA: + loadLuminanceAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + break; + case GL_RGB: + loadRGBFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + break; + case GL_RGBA: + loadRGBAFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + break; + default: UNREACHABLE(); + } + break; + case GL_HALF_FLOAT_OES: + switch (format) + { + // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D + case GL_ALPHA: + loadAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + break; + case GL_LUMINANCE: + loadLuminanceHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + break; + case GL_LUMINANCE_ALPHA: + loadLuminanceAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + break; + case GL_RGB: + loadRGBHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + break; + case GL_RGBA: + loadRGBAHalfFloatImageData(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, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast<const unsigned char*>(input) + y * inputPitch; + dest = static_cast<unsigned char*>(output) + (y + 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::loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch); + dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = 0; + dest[4 * x + 1] = 0; + dest[4 * x + 2] = 0; + dest[4 * x + 3] = source[x]; + } + } +} + +void Texture::loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const unsigned short *source = NULL; + unsigned short *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); + dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = 0; + dest[4 * x + 1] = 0; + dest[4 * x + 2] = 0; + dest[4 * x + 3] = source[x]; + } + } +} + +void Texture::loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const +{ + const int destBytesPerPixel = native? 1: 4; + 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 * destBytesPerPixel; + + if (!native) // BGRA8 destination format + { + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x]; + dest[4 * x + 1] = source[x]; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = 0xFF; + } + } + else // L8 destination format + { + memcpy(dest, source, width); + } + } +} + +void Texture::loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch); + dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x]; + dest[4 * x + 1] = source[x]; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = 1.0f; + } + } +} + +void Texture::loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const unsigned short *source = NULL; + unsigned short *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); + dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x]; + dest[4 * x + 1] = source[x]; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1 + } + } +} + +void Texture::loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const +{ + const int destBytesPerPixel = native? 2: 4; + 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 * destBytesPerPixel; + + if (!native) // BGRA8 destination format + { + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[2*x+0]; + dest[4 * x + 1] = source[2*x+0]; + dest[4 * x + 2] = source[2*x+0]; + dest[4 * x + 3] = source[2*x+1]; + } + } + else + { + memcpy(dest, source, width * 2); + } + } +} + +void Texture::loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch); + dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[2*x+0]; + dest[4 * x + 1] = source[2*x+0]; + dest[4 * x + 2] = source[2*x+0]; + dest[4 * x + 3] = source[2*x+1]; + } + } +} + +void Texture::loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const unsigned short *source = NULL; + unsigned short *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); + dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[2*x+0]; + dest[4 * x + 1] = source[2*x+0]; + dest[4 * x + 2] = source[2*x+0]; + dest[4 * x + 3] = source[2*x+1]; + } + } +} + +void Texture::loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast<const unsigned char*>(input) + y * inputPitch; + dest = static_cast<unsigned char*>(output) + (y + 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, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const unsigned short *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); + dest = static_cast<unsigned char*>(output) + (y + 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::loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch); + dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x * 3 + 0]; + dest[4 * x + 1] = source[x * 3 + 1]; + dest[4 * x + 2] = source[x * 3 + 2]; + dest[4 * x + 3] = 1.0f; + } + } +} + +void Texture::loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const unsigned short *source = NULL; + unsigned short *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); + dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x * 3 + 0]; + dest[4 * x + 1] = source[x * 3 + 1]; + dest[4 * x + 2] = source[x * 3 + 2]; + dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1 + } + } +} + +void Texture::loadRGBAUByteImageDataSSE2(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const unsigned int *source = NULL; + unsigned int *dest = NULL; + __m128i brMask = _mm_set1_epi32(0x00ff00ff); + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch); + dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4); + int x = 0; + + // Make output writes aligned + for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++) + { + unsigned int rgba = source[x]; + dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + } + + for (; x + 3 < width; x += 4) + { + __m128i sourceData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&source[x])); + // Mask out g and a, which don't change + __m128i gaComponents = _mm_andnot_si128(brMask, sourceData); + // Mask out b and r + __m128i brComponents = _mm_and_si128(sourceData, brMask); + // Swap b and r + __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1)); + __m128i result = _mm_or_si128(gaComponents, brSwapped); + _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result); + } + + // Perform leftover writes + for (; x < width; x++) + { + unsigned int rgba = source[x]; + dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + } + } +} + +void Texture::loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const unsigned int *source = NULL; + unsigned int *dest = NULL; + for (int y = 0; y < height; y++) + { + source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch); + dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4); + + for (int x = 0; x < width; x++) + { + unsigned int rgba = source[x]; + dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + } + } +} + +void Texture::loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const unsigned short *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); + dest = static_cast<unsigned char*>(output) + (y + 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, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const unsigned short *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); + dest = static_cast<unsigned char*>(output) + (y + 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::loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch); + dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16); + memcpy(dest, source, width * 16); + } +} + +void Texture::loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast<const unsigned char*>(input) + y * inputPitch; + dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8; + memcpy(dest, source, width * 8); + } +} + +void Texture::loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast<const unsigned char*>(input) + y * inputPitch; + dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4; + memcpy(dest, source, width*4); + } +} + +void Texture::loadCompressedImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const +{ + ASSERT(xoffset % 4 == 0); + ASSERT(yoffset % 4 == 0); + ASSERT(width % 4 == 0 || width == 2 || width == 1); + ASSERT(inputPitch % 8 == 0); + ASSERT(outputPitch % 8 == 0); + + const unsigned int *source = reinterpret_cast<const unsigned int*>(input); + unsigned int *dest = reinterpret_cast<unsigned int*>(output); + + switch (height) + { + case 1: + // Round width up in case it is 1. + for (int x = 0; x < (width + 1) / 2; x += 2) + { + // First 32-bits is two RGB565 colors shared by tile and does not need to be modified. + dest[x] = source[x]; + + // Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors, the last 3 rows being unused. No flipping should occur. + dest[x + 1] = source[x + 1]; + } + break; + case 2: + // Round width up in case it is 1. + for (int x = 0; x < (width + 1) / 2; x += 2) + { + // First 32-bits is two RGB565 colors shared by tile and does not need to be modified. + dest[x] = source[x]; + + // Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors, the last 2 rows being unused. Only the top 2 rows should be flipped. + dest[x + 1] = ((source[x + 1] << 8) & 0x0000FF00) | + ((source[x + 1] >> 8) & 0x000000FF); + } + break; + default: + ASSERT(height % 4 == 0); + for (int y = 0; y < height / 4; ++y) + { + const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch); + unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8); + + // Round width up in case it is 1. + for (int x = 0; x < (width + 1) / 2; x += 2) + { + // First 32-bits is two RGB565 colors shared by tile and does not need to be modified. + dest[x] = source[x]; + + // Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors. All rows should be flipped. + dest[x + 1] = (source[x + 1] >> 24) | + ((source[x + 1] << 8) & 0x00FF0000) | + ((source[x + 1] >> 8) & 0x0000FF00) | + (source[x + 1] << 24); + } + } + break; + } +} + +void Texture::createSurface(Image *image) +{ + IDirect3DTexture9 *newTexture = NULL; + IDirect3DSurface9 *newSurface = NULL; + + if (image->width != 0 && image->height != 0) + { + int levelToFetch = 0; + GLsizei requestWidth = image->width; + GLsizei requestHeight = image->height; + if (IsCompressed(image->format) && (image->width % 4 != 0 || image->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, image->getD3DFormat(), + 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 (image->surface) + { + image->surface->Release(); + } + + image->surface = newSurface; +} + +void Texture::setImage(GLint unpackAlignment, const void *pixels, Image *image) +{ + createSurface(image); + + if (pixels != NULL && image->surface != NULL) + { + D3DSURFACE_DESC description; + image->surface->GetDesc(&description); + + D3DLOCKED_RECT locked; + HRESULT result = image->surface->LockRect(&locked, NULL, 0); + + ASSERT(SUCCEEDED(result)); + + if (SUCCEEDED(result)) + { + loadImageData(0, 0, image->width, image->height, image->format, image->type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description); + image->surface->UnlockRect(); + } + + image->dirty = true; + mDirtyImage = true; + } +} + +void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image) +{ + createSurface(image); + + if (pixels != NULL && image->surface != NULL) + { + D3DLOCKED_RECT locked; + HRESULT result = image->surface->LockRect(&locked, NULL, 0); + + ASSERT(SUCCEEDED(result)); + + if (SUCCEEDED(result)) + { + int inputPitch = ComputeCompressedPitch(image->width, image->format); + int inputSize = ComputeCompressedSize(image->width, image->height, image->format); + loadCompressedImageData(0, 0, image->width, image->height, -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits); + image->surface->UnlockRect(); + } + + image->dirty = true; + mDirtyImage = true; + } +} + +bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image) +{ + if (width + xoffset > image->width || height + yoffset > image->height) + { + error(GL_INVALID_VALUE); + return false; + } + + if (IsCompressed(image->format)) + { + error(GL_INVALID_OPERATION); + return false; + } + + if (format != image->format) + { + error(GL_INVALID_OPERATION); + return false; + } + + if (!image->surface) + { + createSurface(image); + } + + if (pixels != NULL && image->surface != NULL) + { + D3DSURFACE_DESC description; + image->surface->GetDesc(&description); + + D3DLOCKED_RECT locked; + HRESULT result = image->surface->LockRect(&locked, NULL, 0); + + ASSERT(SUCCEEDED(result)); + + if (SUCCEEDED(result)) + { + loadImageData(xoffset, transformPixelYOffset(yoffset, height, image->height), width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description); + image->surface->UnlockRect(); + } + + image->dirty = true; + mDirtyImage = true; + } + + return true; +} + +bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image) +{ + if (width + xoffset > image->width || height + yoffset > image->height) + { + error(GL_INVALID_VALUE); + return false; + } + + if (format != getInternalFormat()) + { + error(GL_INVALID_OPERATION); + return false; + } + + if (!image->surface) + { + createSurface(image); + } + + if (pixels != NULL && image->surface != NULL) + { + RECT updateRegion; + updateRegion.left = xoffset; + updateRegion.right = xoffset + width; + updateRegion.bottom = yoffset + height; + updateRegion.top = yoffset; + + D3DLOCKED_RECT locked; + HRESULT result = image->surface->LockRect(&locked, &updateRegion, 0); + + ASSERT(SUCCEEDED(result)); + + if (SUCCEEDED(result)) + { + int inputPitch = ComputeCompressedPitch(width, format); + int inputSize = ComputeCompressedSize(width, height, format); + loadCompressedImageData(xoffset, transformPixelYOffset(yoffset, height, image->height), width, height, -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits); + image->surface->UnlockRect(); + } + + image->dirty = true; + mDirtyImage = true; + } + + return true; +} + +// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures +void Texture::copyToImage(Image *image, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget) +{ + if (!image->surface) + { + createSurface(image); + + if (!image->surface) + { + ERR("Failed to create an image surface."); + return error(GL_OUT_OF_MEMORY); + } + } + + IDirect3DDevice9 *device = getDevice(); + IDirect3DSurface9 *renderTargetData = NULL; + D3DSURFACE_DESC description; + renderTarget->GetDesc(&description); + + HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL); + + if (FAILED(result)) + { + ERR("Could not create matching destination surface."); + return error(GL_OUT_OF_MEMORY); + } + + result = device->GetRenderTargetData(renderTarget, renderTargetData); + + if (FAILED(result)) + { + ERR("GetRenderTargetData unexpectedly failed."); + renderTargetData->Release(); + return error(GL_OUT_OF_MEMORY); + } + + RECT sourceRect = transformPixelRect(x, y, width, height, description.Height); + int destYOffset = transformPixelYOffset(yoffset, height, image->height); + RECT destRect = {xoffset, destYOffset, xoffset + width, destYOffset + height}; + + if (image->isRenderable()) + { + result = D3DXLoadSurfaceFromSurface(image->surface, NULL, &destRect, renderTargetData, NULL, &sourceRect, D3DX_FILTER_BOX, 0); + + if (FAILED(result)) + { + ERR("Copying surfaces unexpectedly failed."); + renderTargetData->Release(); + return error(GL_OUT_OF_MEMORY); + } + } + else + { + D3DLOCKED_RECT sourceLock = {0}; + result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0); + + if (FAILED(result)) + { + ERR("Failed to lock the source surface (rectangle might be invalid)."); + renderTargetData->Release(); + return error(GL_OUT_OF_MEMORY); + } + + D3DLOCKED_RECT destLock = {0}; + result = image->surface->LockRect(&destLock, &destRect, 0); + + if (FAILED(result)) + { + ERR("Failed to lock the destination surface (rectangle might be invalid)."); + renderTargetData->UnlockRect(); + renderTargetData->Release(); + return error(GL_OUT_OF_MEMORY); + } + + if (destLock.pBits && sourceLock.pBits) + { + unsigned char *source = (unsigned char*)sourceLock.pBits; + unsigned char *dest = (unsigned char*)destLock.pBits; + + switch (description.Format) + { + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + switch(image->getD3DFormat()) + { + case D3DFMT_L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + dest[x] = source[x * 4 + 2]; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_A8L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + dest[x * 2 + 0] = source[x * 4 + 2]; + dest[x * 2 + 1] = source[x * 4 + 3]; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + case D3DFMT_R5G6B5: + switch(image->getD3DFormat()) + { + case D3DFMT_L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned char red = source[x * 2 + 1] & 0xF8; + dest[x] = red | (red >> 5); + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + case D3DFMT_A1R5G5B5: + switch(image->getD3DFormat()) + { + case D3DFMT_L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned char red = source[x * 2 + 1] & 0x7C; + dest[x] = (red << 1) | (red >> 4); + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_A8L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned char red = source[x * 2 + 1] & 0x7C; + dest[x * 2 + 0] = (red << 1) | (red >> 4); + dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + default: + UNREACHABLE(); + } + } + + image->surface->UnlockRect(); + renderTargetData->UnlockRect(); + } + + renderTargetData->Release(); + + image->dirty = true; + mDirtyImage = true; +} + +IDirect3DBaseTexture9 *Texture::getTexture() +{ + if (!isComplete()) + { + return NULL; + } + + if (!getBaseTexture()) + { + createTexture(); + } + + updateTexture(); + + return getBaseTexture(); +} + +bool Texture::isDirtyParameter() const +{ + return mDirtyParameter; +} + +bool Texture::isDirtyImage() const +{ + return mDirtyImage; +} + +void Texture::resetDirty() +{ + mDirtyParameter = false; + mDirtyImage = false; +} + +unsigned int Texture::getSerial() const +{ + return mSerial; +} + +GLint Texture::creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const +{ + if ((isPow2(width) && isPow2(height)) || getContext()->supportsNonPower2Texture()) + { + 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 getBaseTexture() ? getBaseTexture()->GetLevelCount() : 0; +} + +unsigned int Texture::issueSerial() +{ + return mCurrentSerial++; +} + +Texture2D::Texture2D(GLuint id) : Texture(id) +{ + mTexture = NULL; + mSurface = NULL; +} + +Texture2D::~Texture2D() +{ + mColorbufferProxy.set(NULL); + + if (mTexture) + { + mTexture->Release(); + mTexture = NULL; + } + + if (mSurface) + { + mSurface->setBoundTexture(NULL); + mSurface = NULL; + } +} + +GLenum Texture2D::getTarget() const +{ + return GL_TEXTURE_2D; +} + +GLsizei Texture2D::getWidth() const +{ + return mImageArray[0].width; +} + +GLsizei Texture2D::getHeight() const +{ + return mImageArray[0].height; +} + +GLenum Texture2D::getInternalFormat() const +{ + return mImageArray[0].format; +} + +GLenum Texture2D::getType() const +{ + return mImageArray[0].type; +} + +D3DFORMAT Texture2D::getD3DFormat() const +{ + return mImageArray[0].getD3DFormat(); +} + +void Texture2D::redefineTexture(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type, bool forceRedefine) +{ + GLsizei textureWidth = mImageArray[0].width; + GLsizei textureHeight = mImageArray[0].height; + GLenum textureFormat = mImageArray[0].format; + GLenum textureType = mImageArray[0].type; + + mImageArray[level].width = width; + mImageArray[level].height = height; + mImageArray[level].format = format; + mImageArray[level].type = type; + + if (!mTexture) + { + return; + } + + bool widthOkay = (textureWidth >> level == width) || (textureWidth >> level == 0 && width == 1); + bool heightOkay = (textureHeight >> level == height) || (textureHeight >> level == 0 && height == 1); + bool textureOkay = (widthOkay && heightOkay && textureFormat == format && textureType == type); + + if (!textureOkay || forceRedefine || mSurface) // Purge all the levels and the texture. + { + for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + if (mImageArray[i].surface != NULL) + { + mImageArray[i].surface->Release(); + mImageArray[i].surface = NULL; + mImageArray[i].dirty = true; + } + } + + if (mTexture != NULL) + { + mTexture->Release(); + mTexture = NULL; + mDirtyImage = true; + mIsRenderable = false; + } + + if (mSurface) + { + mSurface->setBoundTexture(NULL); + mSurface = NULL; + } + + mColorbufferProxy.set(NULL); + } +} + +void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +{ + redefineTexture(level, format, width, height, type, false); + + Texture::setImage(unpackAlignment, pixels, &mImageArray[level]); +} + +void Texture2D::bindTexImage(egl::Surface *surface) +{ + GLenum format; + + switch(surface->getFormat()) + { + case D3DFMT_A8R8G8B8: + format = GL_RGBA; + break; + case D3DFMT_X8R8G8B8: + format = GL_RGB; + break; + default: + UNIMPLEMENTED(); + return; + } + + redefineTexture(0, format, surface->getWidth(), surface->getHeight(), GL_UNSIGNED_BYTE, true); + + IDirect3DTexture9 *texture = surface->getOffscreenTexture(); + + mTexture = texture; + mDirtyImage = true; + mIsRenderable = true; + mSurface = surface; + mSurface->setBoundTexture(this); +} + +void Texture2D::releaseTexImage() +{ + redefineTexture(0, GL_RGB, 0, 0, GL_UNSIGNED_BYTE, true); +} + +void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) +{ + redefineTexture(level, format, width, height, GL_UNSIGNED_BYTE, false); + + Texture::setCompressedImage(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 *image = &mImageArray[level]; + + RECT sourceRect = transformPixelRect(xoffset, yoffset, width, height, image->height);; + + POINT destPoint; + destPoint.x = sourceRect.left; + destPoint.y = sourceRect.top; + + result = getDevice()->UpdateSurface(image->surface, &sourceRect, destLevel, &destPoint); + ASSERT(SUCCEEDED(result)); + + destLevel->Release(); + + image->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 format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +{ + IDirect3DSurface9 *renderTarget = source->getRenderTarget(); + + if (!renderTarget) + { + ERR("Failed to retrieve the render target."); + return error(GL_OUT_OF_MEMORY); + } + + redefineTexture(level, format, width, height, GL_UNSIGNED_BYTE, false); + + if (!mImageArray[level].isRenderable()) + { + copyToImage(&mImageArray[level], 0, 0, x, y, width, height, renderTarget); + } + else + { + if (!mTexture || !mIsRenderable) + { + convertToRenderTarget(); + } + + updateTexture(); + + if (width != 0 && height != 0 && level < levelCount()) + { + RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight()); + sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth()); + sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight()); + sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth()); + sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight()); + + GLint destYOffset = transformPixelYOffset(0, height, mImageArray[level].height); + + IDirect3DSurface9 *dest; + HRESULT hr = mTexture->GetSurfaceLevel(level, &dest); + + getBlitter()->copy(source->getRenderTarget(), sourceRect, format, 0, destYOffset, dest); + dest->Release(); + } + } +} + +void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +{ + if (xoffset + width > mImageArray[level].width || yoffset + height > mImageArray[level].height) + { + return error(GL_INVALID_VALUE); + } + + IDirect3DSurface9 *renderTarget = source->getRenderTarget(); + + if (!renderTarget) + { + ERR("Failed to retrieve the render target."); + return error(GL_OUT_OF_MEMORY); + } + + redefineTexture(level, mImageArray[level].format, mImageArray[level].width, mImageArray[level].height, GL_UNSIGNED_BYTE, false); + + if (!mImageArray[level].isRenderable() || (!mTexture && !isComplete())) + { + copyToImage(&mImageArray[level], xoffset, yoffset, x, y, width, height, renderTarget); + } + else + { + if (!mTexture || !mIsRenderable) + { + convertToRenderTarget(); + } + + updateTexture(); + + if (level < levelCount()) + { + RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight()); + sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth()); + sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight()); + sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth()); + sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight()); + + GLint destYOffset = transformPixelYOffset(yoffset, height, mImageArray[level].height); + + IDirect3DSurface9 *dest; + HRESULT hr = mTexture->GetSurfaceLevel(level, &dest); + + getBlitter()->copy(source->getRenderTarget(), sourceRect, mImageArray[0].format, xoffset, destYOffset, 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 ((getInternalFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) || + (getInternalFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter())) + { + if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST)) + { + return false; + } + } + + bool npot = getContext()->supportsNonPower2Texture(); + + if (!npot) + { + if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width)) || + (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height))) + { + return false; + } + } + + if (mipmapping) + { + if (!npot) + { + 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].type != mImageArray[0].type) + { + 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(getInternalFormat()); +} + +IDirect3DBaseTexture9 *Texture2D::getBaseTexture() const +{ + return mTexture; +} + +// Constructs a Direct3D 9 texture resource from the texture images +void Texture2D::createTexture() +{ + IDirect3DDevice9 *device = getDevice(); + D3DFORMAT format = mImageArray[0].getD3DFormat(); + GLint levels = creationLevels(mImageArray[0].width, mImageArray[0].height, 0); + + IDirect3DTexture9 *texture = NULL; + HRESULT result = device->CreateTexture(mImageArray[0].width, mImageArray[0].height, levels, 0, format, D3DPOOL_DEFAULT, &texture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return error(GL_OUT_OF_MEMORY); + } + + if (mTexture) + { + mTexture->Release(); + } + + mTexture = texture; + mDirtyImage = true; + mIsRenderable = false; +} + +void Texture2D::updateTexture() +{ + IDirect3DDevice9 *device = getDevice(); + + int levels = levelCount(); + + for (int level = 0; level < levels; level++) + { + if (mImageArray[level].surface && 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; + } + } + } +} + +void Texture2D::convertToRenderTarget() +{ + IDirect3DTexture9 *texture = NULL; + + if (mImageArray[0].width != 0 && mImageArray[0].height != 0) + { + egl::Display *display = getDisplay(); + IDirect3DDevice9 *device = getDevice(); + D3DFORMAT format = mImageArray[0].getD3DFormat(); + GLint levels = creationLevels(mImageArray[0].width, mImageArray[0].height, 0); + + HRESULT result = device->CreateTexture(mImageArray[0].width, mImageArray[0].height, levels, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return error(GL_OUT_OF_MEMORY); + } + + 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); + } + + 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); + } + + 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); + } + + source->Release(); + dest->Release(); + } + } + } + + if (mTexture != NULL) + { + mTexture->Release(); + } + + mTexture = texture; + mDirtyImage = true; + mIsRenderable = true; +} + +void Texture2D::generateMipmaps() +{ + if (!getContext()->supportsNonPower2Texture()) + { + 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(mImageArray[0].width, mImageArray[0].height)); + for (unsigned int i = 1; i <= q; i++) + { + if (mImageArray[i].surface != NULL) + { + mImageArray[i].surface->Release(); + mImageArray[i].surface = NULL; + } + + mImageArray[i].width = std::max(mImageArray[0].width >> i, 1); + mImageArray[i].height = std::max(mImageArray[0].height >> i, 1); + mImageArray[i].format = mImageArray[0].format; + mImageArray[i].type = mImageArray[0].type; + } + + if (mIsRenderable) + { + if (mTexture == NULL) + { + ERR(" failed because mTexture was null."); + return; + } + + 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(); + + mImageArray[i].dirty = false; + } + } + else + { + for (unsigned int i = 1; i <= q; i++) + { + createSurface(&mImageArray[i]); + + if (mImageArray[i].surface == NULL) + { + return error(GL_OUT_OF_MEMORY); + } + + if (FAILED(D3DXLoadSurfaceFromSurface(mImageArray[i].surface, NULL, NULL, mImageArray[i - 1].surface, NULL, NULL, D3DX_FILTER_BOX, 0))) + { + ERR(" failed to load filter %d to %d.", i - 1, i); + } + + mImageArray[i].dirty = true; + } + } +} + +Renderbuffer *Texture2D::getRenderbuffer(GLenum target) +{ + if (target != GL_TEXTURE_2D) + { + return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL); + } + + if (mColorbufferProxy.get() == NULL) + { + mColorbufferProxy.set(new Renderbuffer(id(), new Colorbuffer(this, target))); + } + + return mColorbufferProxy.get(); +} + +IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target) +{ + ASSERT(target == GL_TEXTURE_2D); + + if (!mIsRenderable) + { + convertToRenderTarget(); + } + + if (mTexture == NULL) + { + return NULL; + } + + updateTexture(); + + IDirect3DSurface9 *renderTarget = NULL; + mTexture->GetSurfaceLevel(0, &renderTarget); + + return renderTarget; +} + +TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id) +{ + mTexture = NULL; +} + +TextureCubeMap::~TextureCubeMap() +{ + for (int i = 0; i < 6; i++) + { + mFaceProxies[i].set(NULL); + } + + if (mTexture) + { + mTexture->Release(); + mTexture = NULL; + } +} + +GLenum TextureCubeMap::getTarget() const +{ + return GL_TEXTURE_CUBE_MAP; +} + +GLsizei TextureCubeMap::getWidth() const +{ + return mImageArray[0][0].width; +} + +GLsizei TextureCubeMap::getHeight() const +{ + return mImageArray[0][0].height; +} + +GLenum TextureCubeMap::getInternalFormat() const +{ + return mImageArray[0][0].format; +} + +GLenum TextureCubeMap::getType() const +{ + return mImageArray[0][0].type; +} + +D3DFORMAT TextureCubeMap::getD3DFormat() const +{ + return mImageArray[0][0].getD3DFormat(); +} + +void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +{ + setImage(0, level, width, height, format, type, unpackAlignment, pixels); +} + +void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +{ + setImage(1, level, width, height, format, type, unpackAlignment, pixels); +} + +void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +{ + setImage(2, level, width, height, format, type, unpackAlignment, pixels); +} + +void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +{ + setImage(3, level, width, height, format, type, unpackAlignment, pixels); +} + +void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +{ + setImage(4, level, width, height, format, type, unpackAlignment, pixels); +} + +void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +{ + setImage(5, level, width, height, format, type, unpackAlignment, pixels); +} + +void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) +{ + redefineTexture(faceIndex(face), level, format, width, height, GL_UNSIGNED_BYTE); + + Texture::setCompressedImage(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(faceTarget, level); + ASSERT(destLevel != NULL); + + if (destLevel != NULL) + { + Image *image = &mImageArray[face][level]; + + RECT sourceRect = transformPixelRect(xoffset, yoffset, width, height, image->height);; + + POINT destPoint; + destPoint.x = sourceRect.left; + destPoint.y = sourceRect.top; + + HRESULT result = getDevice()->UpdateSurface(image->surface, &sourceRect, destLevel, &destPoint); + ASSERT(SUCCEEDED(result)); + + destLevel->Release(); + + image->dirty = false; + } + } +} + +void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +{ + if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(target)][level])) + { + commitRect(target, level, xoffset, yoffset, width, height); + } +} + +void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) +{ + if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(target)][level])) + { + commitRect(target, 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 ((getInternalFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) || + (getInternalFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter())) + { + if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST)) + { + return false; + } + } + + bool npot = getContext()->supportsNonPower2Texture(); + + if (!npot) + { + if ((getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE) && !isPow2(size)) + { + return false; + } + } + + if (mipmapping) + { + if (!npot) + { + if (!isPow2(size)) + { + 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].type != mImageArray[0][0].type) + { + 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(getInternalFormat()); +} + +IDirect3DBaseTexture9 *TextureCubeMap::getBaseTexture() const +{ + return mTexture; +} + +// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one +void TextureCubeMap::createTexture() +{ + IDirect3DDevice9 *device = getDevice(); + D3DFORMAT format = mImageArray[0][0].getD3DFormat(); + GLint levels = creationLevels(mImageArray[0][0].width, 0); + + IDirect3DCubeTexture9 *texture = NULL; + HRESULT result = device->CreateCubeTexture(mImageArray[0][0].width, levels, 0, format, D3DPOOL_DEFAULT, &texture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return error(GL_OUT_OF_MEMORY); + } + + if (mTexture) + { + mTexture->Release(); + } + + mTexture = texture; + mDirtyImage = true; + mIsRenderable = false; +} + +void TextureCubeMap::updateTexture() +{ + IDirect3DDevice9 *device = getDevice(); + + for (int face = 0; face < 6; face++) + { + int levels = levelCount(); + for (int level = 0; level < levels; level++) + { + Image *image = &mImageArray[face][level]; + + if (image->surface && image->dirty) + { + IDirect3DSurface9 *levelSurface = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level); + ASSERT(levelSurface != NULL); + + if (levelSurface != NULL) + { + HRESULT result = device->UpdateSurface(image->surface, NULL, levelSurface, NULL); + ASSERT(SUCCEEDED(result)); + + levelSurface->Release(); + + image->dirty = false; + } + } + } + } +} + +void TextureCubeMap::convertToRenderTarget() +{ + IDirect3DCubeTexture9 *texture = NULL; + + if (mImageArray[0][0].width != 0) + { + egl::Display *display = getDisplay(); + IDirect3DDevice9 *device = getDevice(); + D3DFORMAT format = mImageArray[0][0].getD3DFormat(); + GLint levels = creationLevels(mImageArray[0][0].width, 0); + + HRESULT result = device->CreateCubeTexture(mImageArray[0][0].width, levels, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return error(GL_OUT_OF_MEMORY); + } + + 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); + } + + 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); + } + + 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); + } + } + } + } + } + + if (mTexture != NULL) + { + mTexture->Release(); + } + + mTexture = texture; + mDirtyImage = true; + mIsRenderable = true; +} + +void TextureCubeMap::setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +{ + redefineTexture(faceIndex, level, format, width, height, type); + + Texture::setImage(unpackAlignment, pixels, &mImageArray[faceIndex][level]); +} + +unsigned int TextureCubeMap::faceIndex(GLenum face) +{ + META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1); + META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2); + META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3); + META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4); + META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5); + + return face - GL_TEXTURE_CUBE_MAP_POSITIVE_X; +} + +void TextureCubeMap::redefineTexture(int face, GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type) +{ + GLsizei textureWidth = mImageArray[0][0].width; + GLsizei textureHeight = mImageArray[0][0].height; + GLenum textureFormat = mImageArray[0][0].format; + GLenum textureType = mImageArray[0][0].type; + + mImageArray[face][level].width = width; + mImageArray[face][level].height = height; + mImageArray[face][level].format = format; + mImageArray[face][level].type = type; + + if (!mTexture) + { + return; + } + + bool sizeOkay = (textureWidth >> level == width); + bool textureOkay = (sizeOkay && textureFormat == format && textureType == type); + + if (!textureOkay) // Purge all the levels and the texture. + { + for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + for (int f = 0; f < 6; f++) + { + if (mImageArray[f][i].surface != NULL) + { + mImageArray[f][i].surface->Release(); + mImageArray[f][i].surface = NULL; + mImageArray[f][i].dirty = true; + } + } + } + + if (mTexture != NULL) + { + mTexture->Release(); + mTexture = NULL; + mDirtyImage = true; + mIsRenderable = false; + } + } +} + +void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +{ + IDirect3DSurface9 *renderTarget = source->getRenderTarget(); + + if (!renderTarget) + { + ERR("Failed to retrieve the render target."); + return error(GL_OUT_OF_MEMORY); + } + + unsigned int faceindex = faceIndex(target); + redefineTexture(faceindex, level, format, width, height, GL_UNSIGNED_BYTE); + + if (!mImageArray[faceindex][level].isRenderable()) + { + copyToImage(&mImageArray[faceindex][level], 0, 0, x, y, width, height, renderTarget); + } + else + { + if (!mTexture || !mIsRenderable) + { + convertToRenderTarget(); + } + + updateTexture(); + + ASSERT(width == height); + + if (width > 0 && level < levelCount()) + { + RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight()); + sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth()); + sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight()); + sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth()); + sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight()); + + GLint destYOffset = transformPixelYOffset(0, height, mImageArray[faceindex][level].width); + + IDirect3DSurface9 *dest = getCubeMapSurface(target, level); + + getBlitter()->copy(source->getRenderTarget(), sourceRect, format, 0, destYOffset, dest); + dest->Release(); + } + } +} + +IDirect3DSurface9 *TextureCubeMap::getCubeMapSurface(GLenum face, unsigned int level) +{ + if (mTexture == NULL) + { + UNREACHABLE(); + return NULL; + } + + IDirect3DSurface9 *surface = NULL; + + HRESULT hr = mTexture->GetCubeMapSurface(es2dx::ConvertCubeFace(face), level, &surface); + + return (SUCCEEDED(hr)) ? surface : NULL; +} + +void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +{ + GLsizei size = mImageArray[faceIndex(target)][level].width; + + if (xoffset + width > size || yoffset + height > size) + { + return error(GL_INVALID_VALUE); + } + + IDirect3DSurface9 *renderTarget = source->getRenderTarget(); + + if (!renderTarget) + { + ERR("Failed to retrieve the render target."); + return error(GL_OUT_OF_MEMORY); + } + + unsigned int faceindex = faceIndex(target); + redefineTexture(faceindex, level, mImageArray[faceindex][level].format, mImageArray[faceindex][level].width, mImageArray[faceindex][level].height, GL_UNSIGNED_BYTE); + + if (!mImageArray[faceindex][level].isRenderable() || (!mTexture && !isComplete())) + { + copyToImage(&mImageArray[faceindex][level], 0, 0, x, y, width, height, renderTarget); + } + else + { + if (!mTexture || !mIsRenderable) + { + convertToRenderTarget(); + } + + updateTexture(); + + if (level < levelCount()) + { + RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight()); + sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth()); + sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight()); + sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth()); + sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight()); + + GLint destYOffset = transformPixelYOffset(yoffset, height, mImageArray[faceindex][level].width); + + IDirect3DSurface9 *dest = getCubeMapSurface(target, level); + + getBlitter()->copy(source->getRenderTarget(), sourceRect, mImageArray[0][0].format, xoffset, destYOffset, 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 (!isCubeComplete()) + { + return error(GL_INVALID_OPERATION); + } + + if (!getContext()->supportsNonPower2Texture()) + { + if (!isPow2(mImageArray[0][0].width)) + { + 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].width = std::max(mImageArray[f][0].width >> i, 1); + mImageArray[f][i].height = mImageArray[f][i].width; + mImageArray[f][i].format = mImageArray[f][0].format; + mImageArray[f][i].type = mImageArray[f][0].type; + } + } + + if (mIsRenderable) + { + if (mTexture == NULL) + { + return; + } + + for (unsigned int f = 0; f < 6; f++) + { + for (unsigned int i = 1; i <= q; i++) + { + IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i-1); + IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i); + + if (upper != NULL && lower != NULL) + { + getBlitter()->boxFilter(upper, lower); + } + + if (upper != NULL) upper->Release(); + if (lower != NULL) lower->Release(); + + mImageArray[f][i].dirty = false; + } + } + } + else + { + for (unsigned int f = 0; f < 6; f++) + { + for (unsigned int i = 1; i <= q; i++) + { + createSurface(&mImageArray[f][i]); + if (mImageArray[f][i].surface == NULL) + { + return error(GL_OUT_OF_MEMORY); + } + + if (FAILED(D3DXLoadSurfaceFromSurface(mImageArray[f][i].surface, NULL, NULL, mImageArray[f][i - 1].surface, NULL, NULL, D3DX_FILTER_BOX, 0))) + { + ERR(" failed to load filter %d to %d.", i - 1, i); + } + + mImageArray[f][i].dirty = true; + } + } + } +} + +Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target) +{ + if (!IsCubemapTextureTarget(target)) + { + return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL); + } + + unsigned int face = faceIndex(target); + + if (mFaceProxies[face].get() == NULL) + { + mFaceProxies[face].set(new Renderbuffer(id(), new Colorbuffer(this, target))); + } + + return mFaceProxies[face].get(); +} + +IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target) +{ + ASSERT(IsCubemapTextureTarget(target)); + + if (!mIsRenderable) + { + convertToRenderTarget(); + } + + if (mTexture == NULL) + { + return NULL; + } + + updateTexture(); + + IDirect3DSurface9 *renderTarget = NULL; + mTexture->GetCubeMapSurface(es2dx::ConvertCubeFace(target), 0, &renderTarget); + + return renderTarget; +} + +} diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.h new file mode 100644 index 000000000..5bdb2fb0f --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.h @@ -0,0 +1,312 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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/RefCountObject.h" +#include "libGLESv2/utilities.h" +#include "common/debug.h" + +namespace egl +{ +class Surface; +} + +namespace gl +{ +class Blit; +class Framebuffer; + +enum +{ + // These are the maximums the implementation can support + // The actual GL caps are limited by the device caps + // and should be queried from the Context + IMPLEMENTATION_MAX_TEXTURE_SIZE = 16384, + IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 16384, + + IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE +}; + +class 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; + + virtual GLsizei getWidth() const = 0; + virtual GLsizei getHeight() const = 0; + virtual GLenum getInternalFormat() const = 0; + virtual GLenum getType() const = 0; + virtual D3DFORMAT getD3DFormat() const = 0; + + virtual bool isComplete() const = 0; + virtual bool isCompressed() const = 0; + + IDirect3DBaseTexture9 *getTexture(); + virtual Renderbuffer *getRenderbuffer(GLenum target) = 0; + + virtual void generateMipmaps() = 0; + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) = 0; + + bool isDirtyParameter() const; + bool isDirtyImage() const; + void resetDirty(); + unsigned int getSerial() 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: + friend class Colorbuffer; + + // Helper structure representing a single image layer + struct Image + { + Image(); + ~Image(); + + bool isRenderable() const; + D3DFORMAT getD3DFormat() const; + + GLsizei width; + GLsizei height; + GLenum format; + GLenum type; + + bool dirty; + + IDirect3DSurface9 *surface; + }; + + void setImage(GLint unpackAlignment, const void *pixels, Image *image); + bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image); + void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image); + bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image); + void copyToImage(Image *image, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget); + + GLint creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const; + GLint creationLevels(GLsizei size, GLint maxlevel) const; + + virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0; + virtual void createTexture() = 0; + virtual void updateTexture() = 0; + virtual void convertToRenderTarget() = 0; + virtual IDirect3DSurface9 *getRenderTarget(GLenum target) = 0; + + void createSurface(Image *image); + + Blit *getBlitter(); + + int levelCount() const; + + GLenum mMinFilter; + GLenum mMagFilter; + GLenum mWrapS; + GLenum mWrapT; + bool mDirtyParameter; + + bool mDirtyImage; + + bool mIsRenderable; + + 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, D3DSURFACE_DESC *description) const; + + void loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const; + void loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const; + void loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadRGBAUByteImageDataSSE2(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadCompressedImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) const; + + static unsigned int issueSerial(); + + const unsigned int mSerial; + + static unsigned int mCurrentSerial; +}; + +class Texture2D : public Texture +{ + public: + explicit Texture2D(GLuint id); + + ~Texture2D(); + + virtual GLenum getTarget() const; + + virtual GLsizei getWidth() const; + virtual GLsizei getHeight() const; + virtual GLenum getInternalFormat() const; + virtual GLenum getType() const; + virtual D3DFORMAT getD3DFormat() const; + + void setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); + void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); + void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); + void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); + void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); + void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); + + virtual bool isComplete() const; + virtual bool isCompressed() const; + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); + + virtual void generateMipmaps(); + + virtual Renderbuffer *getRenderbuffer(GLenum target); + + private: + DISALLOW_COPY_AND_ASSIGN(Texture2D); + + virtual IDirect3DBaseTexture9 *getBaseTexture() const; + virtual void createTexture(); + virtual void updateTexture(); + virtual void convertToRenderTarget(); + virtual IDirect3DSurface9 *getRenderTarget(GLenum target); + + void redefineTexture(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type, bool force); + void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + + Image mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + IDirect3DTexture9 *mTexture; + egl::Surface *mSurface; + + BindingPointer<Renderbuffer> mColorbufferProxy; +}; + +class TextureCubeMap : public Texture +{ + public: + explicit TextureCubeMap(GLuint id); + + ~TextureCubeMap(); + + virtual GLenum getTarget() const; + + virtual GLsizei getWidth() const; + virtual GLsizei getHeight() const; + virtual GLenum getInternalFormat() const; + virtual GLenum getType() const; + virtual D3DFORMAT getD3DFormat() const; + + void setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); + void setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); + void setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); + void setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); + void setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); + void setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); + + void setCompressedImage(GLenum face, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); + + void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); + void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); + void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); + + virtual bool isComplete() const; + virtual bool isCompressed() const; + + virtual void generateMipmaps(); + + virtual Renderbuffer *getRenderbuffer(GLenum target); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureCubeMap); + + virtual IDirect3DBaseTexture9 *getBaseTexture() const; + virtual void createTexture(); + virtual void updateTexture(); + virtual void convertToRenderTarget(); + virtual IDirect3DSurface9 *getRenderTarget(GLenum target); + + // face is one of the GL_TEXTURE_CUBE_MAP_* enumerants. + // Returns NULL if the call underlying Direct3D call fails. + IDirect3DSurface9 *getCubeMapSurface(GLenum face, unsigned int level); + + static unsigned int faceIndex(GLenum face); + + bool isCubeComplete() const; + + void setImage(int faceIndex, GLint level, 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); + void redefineTexture(int faceIndex, GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type); + + Image mImageArray[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + IDirect3DCubeTexture9 *mTexture; + + BindingPointer<Renderbuffer> mFaceProxies[6]; +}; +} + +#endif // LIBGLESV2_TEXTURE_H_ diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/VertexDataManager.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/VertexDataManager.cpp new file mode 100644 index 000000000..a7716cee0 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/VertexDataManager.cpp @@ -0,0 +1,733 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexDataManager.h: Defines the VertexDataManager, a class that +// runs the Buffer translation process. + +#include "libGLESv2/VertexDataManager.h" + +#include "common/debug.h" + +#include "libGLESv2/Buffer.h" +#include "libGLESv2/Program.h" +#include "libGLESv2/main.h" + +#include "libGLESv2/vertexconversion.h" +#include "libGLESv2/IndexDataManager.h" + +namespace +{ + enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 }; +} + +namespace gl +{ + +VertexDataManager::VertexDataManager(Context *context, IDirect3DDevice9 *device) : mContext(context), mDevice(device) +{ + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + mDirtyCurrentValue[i] = true; + mCurrentValueBuffer[i] = NULL; + } + + const D3DCAPS9 &caps = context->getDeviceCaps(); + checkVertexCaps(caps.DeclTypes); + + mStreamingBuffer = new StreamingVertexBuffer(mDevice, INITIAL_STREAM_BUFFER_SIZE); + + if (!mStreamingBuffer) + { + ERR("Failed to allocate the streaming vertex buffer."); + } +} + +VertexDataManager::~VertexDataManager() +{ + delete mStreamingBuffer; + + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + delete mCurrentValueBuffer[i]; + } +} + +UINT VertexDataManager::writeAttributeData(ArrayVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute) +{ + Buffer *buffer = attribute.mBoundBuffer.get(); + + int inputStride = attribute.stride(); + int elementSize = attribute.typeSize(); + const FormatConverter &converter = formatConverter(attribute); + UINT streamOffset = 0; + + void *output = NULL; + + if (vertexBuffer) + { + output = vertexBuffer->map(attribute, spaceRequired(attribute, count), &streamOffset); + } + + if (output == NULL) + { + ERR("Failed to map vertex buffer."); + return -1; + } + + const char *input = NULL; + + if (buffer) + { + int offset = attribute.mOffset; + + input = static_cast<const char*>(buffer->data()) + offset; + } + else + { + input = static_cast<const char*>(attribute.mPointer); + } + + input += inputStride * start; + + if (converter.identity && inputStride == elementSize) + { + memcpy(output, input, count * inputStride); + } + else + { + converter.convertArray(input, inputStride, count, output); + } + + vertexBuffer->unmap(); + + return streamOffset; +} + +GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *translated) +{ + if (!mStreamingBuffer) + { + return GL_OUT_OF_MEMORY; + } + + const VertexAttributeArray &attribs = mContext->getVertexAttributes(); + Program *program = mContext->getCurrentProgram(); + + for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + { + translated[attributeIndex].active = (program->getSemanticIndex(attributeIndex) != -1); + } + + // Determine the required storage size per used buffer, and invalidate static buffers that don't contain matching attributes + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active && attribs[i].mArrayEnabled) + { + Buffer *buffer = attribs[i].mBoundBuffer.get(); + StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; + + if (staticBuffer) + { + if (staticBuffer->size() == 0) + { + int totalCount = buffer->size() / attribs[i].stride(); + staticBuffer->addRequiredSpace(spaceRequired(attribs[i], totalCount)); + } + else if (staticBuffer->lookupAttribute(attribs[i]) == -1) + { + // This static buffer doesn't have matching attributes, so fall back to using the streaming buffer + mStreamingBuffer->addRequiredSpaceFor(staticBuffer); + buffer->invalidateStaticData(); + + mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[i], count)); + } + } + else + { + mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[i], count)); + } + } + } + + // Reserve the required space per used buffer + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active && attribs[i].mArrayEnabled) + { + Buffer *buffer = attribs[i].mBoundBuffer.get(); + ArrayVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; + ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : mStreamingBuffer; + + if (vertexBuffer) + { + vertexBuffer->reserveRequiredSpace(); + } + } + } + + // Perform the vertex data translations + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active) + { + if (attribs[i].mArrayEnabled) + { + Buffer *buffer = attribs[i].mBoundBuffer.get(); + + if (!buffer && attribs[i].mPointer == NULL) + { + // This is an application error that would normally result in a crash, but we catch it and return an error + ERR("An enabled vertex array has no buffer and no pointer."); + return GL_INVALID_OPERATION; + } + + const FormatConverter &converter = formatConverter(attribs[i]); + + StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; + ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : static_cast<ArrayVertexBuffer*>(mStreamingBuffer); + + UINT streamOffset = -1; + + if (staticBuffer) + { + streamOffset = staticBuffer->lookupAttribute(attribs[i]); + + if (streamOffset == -1) + { + // Convert the entire buffer + int totalCount = buffer->size() / attribs[i].stride(); + int startIndex = attribs[i].mOffset / attribs[i].stride(); + + streamOffset = writeAttributeData(staticBuffer, -startIndex, totalCount, attribs[i]); + } + + if (streamOffset != -1) + { + streamOffset += (start + attribs[i].mOffset / attribs[i].stride()) * converter.outputElementSize; + } + } + else + { + streamOffset = writeAttributeData(mStreamingBuffer, start, count, attribs[i]); + } + + if (streamOffset == -1) + { + return GL_OUT_OF_MEMORY; + } + + translated[i].vertexBuffer = vertexBuffer->getBuffer(); + translated[i].type = converter.d3dDeclType; + translated[i].stride = converter.outputElementSize; + translated[i].offset = streamOffset; + } + else + { + if (mDirtyCurrentValue[i]) + { + delete mCurrentValueBuffer[i]; + mCurrentValueBuffer[i] = new ConstantVertexBuffer(mDevice, attribs[i].mCurrentValue[0], attribs[i].mCurrentValue[1], attribs[i].mCurrentValue[2], attribs[i].mCurrentValue[3]); + mDirtyCurrentValue[i] = false; + } + + translated[i].vertexBuffer = mCurrentValueBuffer[i]->getBuffer(); + + translated[i].type = D3DDECLTYPE_FLOAT4; + translated[i].stride = 0; + translated[i].offset = 0; + } + } + } + + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active && attribs[i].mArrayEnabled) + { + Buffer *buffer = attribs[i].mBoundBuffer.get(); + + if (buffer) + { + buffer->promoteStaticUsage(count * attribs[i].typeSize()); + } + } + } + + return GL_NO_ERROR; +} + +std::size_t VertexDataManager::spaceRequired(const VertexAttribute &attrib, std::size_t count) const +{ + return formatConverter(attrib).outputElementSize * count; +} + +// 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 }; +}; + +// 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 VertexDataManager::TranslationDescription VertexDataManager::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1] +{ + TRANSLATIONS_FOR_TYPE(GL_BYTE), + TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE), + TRANSLATIONS_FOR_TYPE(GL_SHORT), + TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT), + TRANSLATIONS_FOR_TYPE(GL_FIXED), + TRANSLATIONS_FOR_TYPE(GL_FLOAT) +}; + +void VertexDataManager::checkVertexCaps(DWORD declTypes) +{ + for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++) + { + for (unsigned int j = 0; j < 2; j++) + { + for (unsigned int k = 0; k < 4; k++) + { + if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0) + { + mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion; + } + else + { + mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion; + } + } + } + } +} + +// This is used to index mAttributeTypes and mPossibleTranslations. +unsigned int VertexDataManager::typeIndex(GLenum type) const +{ + switch (type) + { + case GL_BYTE: return 0; + case GL_UNSIGNED_BYTE: return 1; + case GL_SHORT: return 2; + case GL_UNSIGNED_SHORT: return 3; + case GL_FIXED: return 4; + case GL_FLOAT: return 5; + + default: UNREACHABLE(); return 5; + } +} + +VertexBuffer::VertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags) : mDevice(device), mVertexBuffer(NULL) +{ + if (size > 0) + { + D3DPOOL pool = getDisplay()->getBufferPool(usageFlags); + HRESULT result = device->CreateVertexBuffer(size, usageFlags, 0, pool, &mVertexBuffer, NULL); + + if (FAILED(result)) + { + ERR("Out of memory allocating a vertex buffer of size %lu.", size); + } + } +} + +VertexBuffer::~VertexBuffer() +{ + if (mVertexBuffer) + { + mVertexBuffer->Release(); + } +} + +void VertexBuffer::unmap() +{ + if (mVertexBuffer) + { + mVertexBuffer->Unlock(); + } +} + +IDirect3DVertexBuffer9 *VertexBuffer::getBuffer() const +{ + return mVertexBuffer; +} + +ConstantVertexBuffer::ConstantVertexBuffer(IDirect3DDevice9 *device, float x, float y, float z, float w) : VertexBuffer(device, 4 * sizeof(float), D3DUSAGE_WRITEONLY) +{ + void *buffer = NULL; + + if (mVertexBuffer) + { + HRESULT result = mVertexBuffer->Lock(0, 0, &buffer, 0); + + if (FAILED(result)) + { + ERR("Lock failed with error 0x%08x", result); + } + } + + if (buffer) + { + float *vector = (float*)buffer; + + vector[0] = x; + vector[1] = y; + vector[2] = z; + vector[3] = w; + + mVertexBuffer->Unlock(); + } +} + +ConstantVertexBuffer::~ConstantVertexBuffer() +{ +} + +ArrayVertexBuffer::ArrayVertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags) : VertexBuffer(device, size, usageFlags) +{ + mBufferSize = size; + mWritePosition = 0; + mRequiredSpace = 0; +} + +ArrayVertexBuffer::~ArrayVertexBuffer() +{ +} + +void ArrayVertexBuffer::addRequiredSpace(UINT requiredSpace) +{ + mRequiredSpace += requiredSpace; +} + +void ArrayVertexBuffer::addRequiredSpaceFor(ArrayVertexBuffer *buffer) +{ + mRequiredSpace += buffer->mRequiredSpace; +} + +StreamingVertexBuffer::StreamingVertexBuffer(IDirect3DDevice9 *device, std::size_t initialSize) : ArrayVertexBuffer(device, initialSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY) +{ +} + +StreamingVertexBuffer::~StreamingVertexBuffer() +{ +} + +void *StreamingVertexBuffer::map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *offset) +{ + void *mapPtr = NULL; + + if (mVertexBuffer) + { + HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE); + + if (FAILED(result)) + { + ERR("Lock failed with error 0x%08x", result); + return NULL; + } + + *offset = mWritePosition; + mWritePosition += requiredSpace; + } + + return mapPtr; +} + +void StreamingVertexBuffer::reserveRequiredSpace() +{ + if (mRequiredSpace > mBufferSize) + { + if (mVertexBuffer) + { + mVertexBuffer->Release(); + mVertexBuffer = NULL; + } + + mBufferSize = std::max(mRequiredSpace, 3 * mBufferSize / 2); // 1.5 x mBufferSize is arbitrary and should be checked to see we don't have too many reallocations. + + D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); + HRESULT result = mDevice->CreateVertexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, pool, &mVertexBuffer, NULL); + + if (FAILED(result)) + { + ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize); + } + + mWritePosition = 0; + } + else if (mWritePosition + mRequiredSpace > mBufferSize) // Recycle + { + if (mVertexBuffer) + { + void *dummy; + mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); + mVertexBuffer->Unlock(); + } + + mWritePosition = 0; + } + + mRequiredSpace = 0; +} + +StaticVertexBuffer::StaticVertexBuffer(IDirect3DDevice9 *device) : ArrayVertexBuffer(device, 0, D3DUSAGE_WRITEONLY) +{ +} + +StaticVertexBuffer::~StaticVertexBuffer() +{ +} + +void *StaticVertexBuffer::map(const VertexAttribute &attribute, std::size_t requiredSpace, UINT *streamOffset) +{ + void *mapPtr = NULL; + + if (mVertexBuffer) + { + HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, 0); + + if (FAILED(result)) + { + ERR("Lock failed with error 0x%08x", result); + return NULL; + } + + int attributeOffset = attribute.mOffset % attribute.stride(); + VertexElement element = {attribute.mType, attribute.mSize, attribute.mNormalized, attributeOffset, mWritePosition}; + mCache.push_back(element); + + *streamOffset = mWritePosition; + mWritePosition += requiredSpace; + } + + return mapPtr; +} + +void StaticVertexBuffer::reserveRequiredSpace() +{ + if (!mVertexBuffer && mBufferSize == 0) + { + D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_WRITEONLY); + HRESULT result = mDevice->CreateVertexBuffer(mRequiredSpace, D3DUSAGE_WRITEONLY, 0, pool, &mVertexBuffer, NULL); + + if (FAILED(result)) + { + ERR("Out of memory allocating a vertex buffer of size %lu.", mRequiredSpace); + } + + mBufferSize = mRequiredSpace; + } + else if (mVertexBuffer && mBufferSize >= mRequiredSpace) + { + // Already allocated + } + else UNREACHABLE(); // Static vertex buffers can't be resized + + mRequiredSpace = 0; +} + +UINT StaticVertexBuffer::lookupAttribute(const VertexAttribute &attribute) +{ + for (unsigned int element = 0; element < mCache.size(); element++) + { + if (mCache[element].type == attribute.mType && mCache[element].size == attribute.mSize && mCache[element].normalized == attribute.mNormalized) + { + if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride()) + { + return mCache[element].streamOffset; + } + } + } + + return -1; +} + +const VertexDataManager::FormatConverter &VertexDataManager::formatConverter(const VertexAttribute &attribute) const +{ + return mAttributeTypes[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1]; +} +} diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/VertexDataManager.h b/Source/ThirdParty/ANGLE/src/libGLESv2/VertexDataManager.h new file mode 100644 index 000000000..1bd8351d8 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/VertexDataManager.h @@ -0,0 +1,168 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexDataManager.h: Defines the VertexDataManager, a class that +// runs the Buffer translation process. + +#ifndef LIBGLESV2_VERTEXDATAMANAGER_H_ +#define LIBGLESV2_VERTEXDATAMANAGER_H_ + +#include <vector> +#include <cstddef> + +#define GL_APICALL +#include <GLES2/gl2.h> + +#include "libGLESv2/Context.h" + +namespace gl +{ + +struct TranslatedAttribute +{ + bool active; + + D3DDECLTYPE type; + UINT offset; + UINT stride; // 0 means not to advance the read pointer at all + + IDirect3DVertexBuffer9 *vertexBuffer; +}; + +class VertexBuffer +{ + public: + VertexBuffer(IDirect3DDevice9 *device, UINT size, DWORD usageFlags); + virtual ~VertexBuffer(); + + void unmap(); + + IDirect3DVertexBuffer9 *getBuffer() const; + + protected: + IDirect3DDevice9 *const mDevice; + IDirect3DVertexBuffer9 *mVertexBuffer; + + private: + DISALLOW_COPY_AND_ASSIGN(VertexBuffer); +}; + +class ConstantVertexBuffer : public VertexBuffer +{ + public: + ConstantVertexBuffer(IDirect3DDevice9 *device, float x, float y, float z, float w); + ~ConstantVertexBuffer(); +}; + +class ArrayVertexBuffer : public VertexBuffer +{ + public: + ArrayVertexBuffer(IDirect3DDevice9 *device, UINT size, DWORD usageFlags); + ~ArrayVertexBuffer(); + + UINT size() const { return mBufferSize; } + virtual void *map(const VertexAttribute &attribute, UINT requiredSpace, UINT *streamOffset) = 0; + virtual void reserveRequiredSpace() = 0; + void addRequiredSpace(UINT requiredSpace); + void addRequiredSpaceFor(ArrayVertexBuffer *buffer); + + protected: + UINT mBufferSize; + UINT mWritePosition; + UINT mRequiredSpace; +}; + +class StreamingVertexBuffer : public ArrayVertexBuffer +{ + public: + StreamingVertexBuffer(IDirect3DDevice9 *device, UINT initialSize); + ~StreamingVertexBuffer(); + + void *map(const VertexAttribute &attribute, UINT requiredSpace, UINT *streamOffset); + void reserveRequiredSpace(); +}; + +class StaticVertexBuffer : public ArrayVertexBuffer +{ + public: + explicit StaticVertexBuffer(IDirect3DDevice9 *device); + ~StaticVertexBuffer(); + + void *map(const VertexAttribute &attribute, UINT requiredSpace, UINT *streamOffset); + void reserveRequiredSpace(); + + UINT lookupAttribute(const VertexAttribute &attribute); // Returns the offset into the vertex buffer, or -1 if not found + + private: + struct VertexElement + { + GLenum type; + GLint size; + bool normalized; + int attributeOffset; + + UINT streamOffset; + }; + + std::vector<VertexElement> mCache; +}; + +class VertexDataManager +{ + public: + VertexDataManager(Context *context, IDirect3DDevice9 *backend); + virtual ~VertexDataManager(); + + void dirtyCurrentValue(int index) { mDirtyCurrentValue[index] = true; } + + GLenum prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *outAttribs); + + private: + DISALLOW_COPY_AND_ASSIGN(VertexDataManager); + + UINT spaceRequired(const VertexAttribute &attrib, std::size_t count) const; + UINT writeAttributeData(ArrayVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute); + + Context *const mContext; + IDirect3DDevice9 *const mDevice; + + StreamingVertexBuffer *mStreamingBuffer; + + bool mDirtyCurrentValue[MAX_VERTEX_ATTRIBS]; + ConstantVertexBuffer *mCurrentValueBuffer[MAX_VERTEX_ATTRIBS]; + + // Attribute format conversion + struct FormatConverter + { + bool identity; + std::size_t outputElementSize; + void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out); + D3DDECLTYPE d3dDeclType; + }; + + enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; + + FormatConverter mAttributeTypes[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1] + + struct TranslationDescription + { + DWORD capsFlag; + FormatConverter preferredConversion; + FormatConverter fallbackConversion; + }; + + // This table is used to generate mAttributeTypes. + static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1] + + void checkVertexCaps(DWORD declTypes); + + unsigned int typeIndex(GLenum type) const; + const FormatConverter &formatConverter(const VertexAttribute &attribute) const; +}; + +} + +#endif // LIBGLESV2_VERTEXDATAMANAGER_H_ diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp new file mode 100644 index 000000000..f79d60677 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp @@ -0,0 +1,382 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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/main.h" + +namespace +{ + enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) }; +} + +namespace gl +{ + +IndexDataManager::IndexDataManager(Context *context, IDirect3DDevice9 *device) : mDevice(device) +{ + mStreamingBufferShort = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16); + + if (context->supports32bitIndices()) + { + mStreamingBufferInt = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32); + } + else + { + mStreamingBufferInt = NULL; + } +} + +IndexDataManager::~IndexDataManager() +{ + delete mStreamingBufferShort; + delete mStreamingBufferInt; +} + +void convertIndices(GLenum type, const void *input, GLsizei count, void *output) +{ + if (type == GL_UNSIGNED_BYTE) + { + const GLubyte *in = static_cast<const GLubyte*>(input); + GLushort *out = static_cast<GLushort*>(output); + + for (GLsizei i = 0; i < count; i++) + { + out[i] = in[i]; + } + } + else if (type == GL_UNSIGNED_INT) + { + memcpy(output, input, count * sizeof(GLuint)); + } + else if (type == GL_UNSIGNED_SHORT) + { + memcpy(output, input, count * sizeof(GLushort)); + } + else UNREACHABLE(); +} + +template <class IndexType> +void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +{ + *minIndex = indices[0]; + *maxIndex = indices[0]; + + for (GLsizei i = 0; i < count; i++) + { + if (*minIndex > indices[i]) *minIndex = indices[i]; + if (*maxIndex < indices[i]) *maxIndex = indices[i]; + } +} + +void computeRange(GLenum type, const void *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +{ + if (type == GL_UNSIGNED_BYTE) + { + computeRange(static_cast<const GLubyte*>(indices), count, minIndex, maxIndex); + } + else if (type == GL_UNSIGNED_INT) + { + computeRange(static_cast<const GLuint*>(indices), count, minIndex, maxIndex); + } + else if (type == GL_UNSIGNED_SHORT) + { + computeRange(static_cast<const GLushort*>(indices), count, minIndex, maxIndex); + } + else UNREACHABLE(); +} + +GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const void *indices, TranslatedIndexData *translated) +{ + D3DFORMAT format = (type == GL_UNSIGNED_INT) ? D3DFMT_INDEX32 : D3DFMT_INDEX16; + intptr_t offset = reinterpret_cast<intptr_t>(indices); + bool alignedOffset = false; + + if (buffer != NULL) + { + switch (type) + { + case GL_UNSIGNED_BYTE: alignedOffset = (offset % sizeof(GLubyte) == 0); break; + case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break; + case GL_UNSIGNED_INT: alignedOffset = (offset % sizeof(GLuint) == 0); break; + default: UNREACHABLE(); alignedOffset = false; + } + + if (typeSize(type) * count + offset > static_cast<std::size_t>(buffer->size())) + { + return GL_INVALID_OPERATION; + } + + indices = static_cast<const GLubyte*>(buffer->data()) + offset; + } + + StreamingIndexBuffer *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort; + + StaticIndexBuffer *staticBuffer = buffer ? buffer->getIndexBuffer() : NULL; + IndexBuffer *indexBuffer = streamingBuffer; + UINT streamOffset = 0; + + if (staticBuffer && staticBuffer->lookupType(type) && alignedOffset) + { + indexBuffer = staticBuffer; + streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex); + + if (streamOffset == -1) + { + streamOffset = (offset / typeSize(type)) * indexSize(format); + computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); + staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset); + } + } + else + { + int convertCount = count; + + if (staticBuffer) + { + if (staticBuffer->size() == 0 && alignedOffset) + { + indexBuffer = staticBuffer; + convertCount = buffer->size() / typeSize(type); + } + else + { + buffer->invalidateStaticData(); + staticBuffer = NULL; + } + } + + void *output = NULL; + + if (indexBuffer) + { + indexBuffer->reserveSpace(convertCount * indexSize(format), type); + output = indexBuffer->map(indexSize(format) * convertCount, &streamOffset); + } + + if (output == NULL) + { + ERR("Failed to map index buffer."); + return GL_OUT_OF_MEMORY; + } + + convertIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output); + indexBuffer->unmap(); + + computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); + + if (staticBuffer) + { + streamOffset = (offset / typeSize(type)) * indexSize(format); + staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset); + } + } + + translated->indexBuffer = indexBuffer->getBuffer(); + translated->startIndex = streamOffset / indexSize(format); + + return GL_NO_ERROR; +} + +std::size_t IndexDataManager::indexSize(D3DFORMAT format) const +{ + return (format == D3DFMT_INDEX32) ? sizeof(unsigned int) : sizeof(unsigned short); +} + +std::size_t IndexDataManager::typeSize(GLenum type) const +{ + switch (type) + { + case GL_UNSIGNED_INT: return sizeof(GLuint); + case GL_UNSIGNED_SHORT: return sizeof(GLushort); + case GL_UNSIGNED_BYTE: return sizeof(GLubyte); + default: UNREACHABLE(); return sizeof(GLushort); + } +} + +IndexBuffer::IndexBuffer(IDirect3DDevice9 *device, UINT size, D3DFORMAT format) : mDevice(device), mBufferSize(size), mIndexBuffer(NULL) +{ + if (size > 0) + { + D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); + HRESULT result = device->CreateIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, pool, &mIndexBuffer, NULL); + + if (FAILED(result)) + { + ERR("Out of memory allocating an index buffer of size %lu.", size); + } + } +} + +IndexBuffer::~IndexBuffer() +{ + if (mIndexBuffer) + { + mIndexBuffer->Release(); + } +} + +IDirect3DIndexBuffer9 *IndexBuffer::getBuffer() const +{ + return mIndexBuffer; +} + +void IndexBuffer::unmap() +{ + if (mIndexBuffer) + { + mIndexBuffer->Unlock(); + } +} + +StreamingIndexBuffer::StreamingIndexBuffer(IDirect3DDevice9 *device, UINT initialSize, D3DFORMAT format) : IndexBuffer(device, initialSize, format) +{ + mWritePosition = 0; +} + +StreamingIndexBuffer::~StreamingIndexBuffer() +{ +} + +void *StreamingIndexBuffer::map(UINT requiredSpace, UINT *offset) +{ + void *mapPtr = NULL; + + if (mIndexBuffer) + { + HRESULT result = mIndexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE); + + if (FAILED(result)) + { + ERR(" Lock failed with error 0x%08x", result); + return NULL; + } + + *offset = mWritePosition; + mWritePosition += requiredSpace; + } + + return mapPtr; +} + +void StreamingIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type) +{ + if (requiredSpace > mBufferSize) + { + if (mIndexBuffer) + { + mIndexBuffer->Release(); + mIndexBuffer = NULL; + } + + mBufferSize = std::max(requiredSpace, 2 * mBufferSize); + + D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); + HRESULT result = mDevice->CreateIndexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL); + + if (FAILED(result)) + { + ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize); + } + + mWritePosition = 0; + } + else if (mWritePosition + requiredSpace > mBufferSize) // Recycle + { + void *dummy; + mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); + mIndexBuffer->Unlock(); + + mWritePosition = 0; + } +} + +StaticIndexBuffer::StaticIndexBuffer(IDirect3DDevice9 *device) : IndexBuffer(device, 0, D3DFMT_UNKNOWN) +{ + mCacheType = GL_NONE; +} + +StaticIndexBuffer::~StaticIndexBuffer() +{ +} + +void *StaticIndexBuffer::map(UINT requiredSpace, UINT *offset) +{ + void *mapPtr = NULL; + + if (mIndexBuffer) + { + HRESULT result = mIndexBuffer->Lock(0, requiredSpace, &mapPtr, 0); + + if (FAILED(result)) + { + ERR(" Lock failed with error 0x%08x", result); + return NULL; + } + + *offset = 0; + } + + return mapPtr; +} + +void StaticIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type) +{ + if (!mIndexBuffer && mBufferSize == 0) + { + D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_WRITEONLY); + HRESULT result = mDevice->CreateIndexBuffer(requiredSpace, D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL); + + if (FAILED(result)) + { + ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize); + } + + mBufferSize = requiredSpace; + mCacheType = type; + } + else if (mIndexBuffer && mBufferSize >= requiredSpace && mCacheType == type) + { + // Already allocated + } + else UNREACHABLE(); // Static index buffers can't be resized +} + +bool StaticIndexBuffer::lookupType(GLenum type) +{ + return mCacheType == type; +} + +UINT StaticIndexBuffer::lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex) +{ + for (unsigned int range = 0; range < mCache.size(); range++) + { + if (mCache[range].offset == offset && mCache[range].count == count) + { + *minIndex = mCache[range].minIndex; + *maxIndex = mCache[range].maxIndex; + + return mCache[range].streamOffset; + } + } + + return -1; +} + +void StaticIndexBuffer::addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset) +{ + IndexRange indexRange = {offset, count, minIndex, maxIndex, streamOffset}; + mCache.push_back(indexRange); +} + +} 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 000000000..d48249c79 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.h @@ -0,0 +1,120 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// 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 <vector> +#include <cstddef> + +#define GL_APICALL +#include <GLES2/gl2.h> + +#include "libGLESv2/Context.h" + +namespace gl +{ + +struct TranslatedIndexData +{ + UINT minIndex; + UINT maxIndex; + UINT startIndex; + + IDirect3DIndexBuffer9 *indexBuffer; +}; + +class IndexBuffer +{ + public: + IndexBuffer(IDirect3DDevice9 *device, UINT size, D3DFORMAT format); + virtual ~IndexBuffer(); + + UINT size() const { return mBufferSize; } + virtual void *map(UINT requiredSpace, UINT *offset) = 0; + void unmap(); + virtual void reserveSpace(UINT requiredSpace, GLenum type) = 0; + + IDirect3DIndexBuffer9 *getBuffer() const; + + protected: + IDirect3DDevice9 *const mDevice; + + IDirect3DIndexBuffer9 *mIndexBuffer; + UINT mBufferSize; + + private: + DISALLOW_COPY_AND_ASSIGN(IndexBuffer); +}; + +class StreamingIndexBuffer : public IndexBuffer +{ + public: + StreamingIndexBuffer(IDirect3DDevice9 *device, UINT initialSize, D3DFORMAT format); + ~StreamingIndexBuffer(); + + void *map(UINT requiredSpace, UINT *offset); + void reserveSpace(UINT requiredSpace, GLenum type); + + private: + UINT mWritePosition; +}; + +class StaticIndexBuffer : public IndexBuffer +{ + public: + explicit StaticIndexBuffer(IDirect3DDevice9 *device); + ~StaticIndexBuffer(); + + void *map(UINT requiredSpace, UINT *offset); + void reserveSpace(UINT requiredSpace, GLenum type); + + bool lookupType(GLenum type); + UINT lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex); // Returns the offset into the index buffer, or -1 if not found + void addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset); + + private: + GLenum mCacheType; + + struct IndexRange + { + intptr_t offset; + GLsizei count; + + UINT minIndex; + UINT maxIndex; + UINT streamOffset; + }; + + std::vector<IndexRange> mCache; +}; + +class IndexDataManager +{ + public: + IndexDataManager(Context *context, IDirect3DDevice9 *evice); + virtual ~IndexDataManager(); + + GLenum prepareIndexData(GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices, TranslatedIndexData *translated); + + private: + DISALLOW_COPY_AND_ASSIGN(IndexDataManager); + + std::size_t typeSize(GLenum type) const; + std::size_t indexSize(D3DFORMAT format) const; + + IDirect3DDevice9 *const mDevice; + + StreamingIndexBuffer *mStreamingBufferShort; + StreamingIndexBuffer *mStreamingBufferInt; +}; + +} + +#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 000000000..99ece1775 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.cpp @@ -0,0 +1,769 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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 "common/debug.h" + +#include "libGLESv2/Buffer.h" +#include "libGLESv2/Program.h" +#include "libGLESv2/main.h" + +#include "libGLESv2/geometry/vertexconversion.h" +#include "libGLESv2/geometry/IndexDataManager.h" + +namespace +{ + enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 }; +} + +namespace gl +{ + +VertexDataManager::VertexDataManager(Context *context, IDirect3DDevice9 *device) : mContext(context), mDevice(device) +{ + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + mDirtyCurrentValue[i] = true; + mCurrentValueBuffer[i] = NULL; + } + + const D3DCAPS9 &caps = context->getDeviceCaps(); + checkVertexCaps(caps.DeclTypes); + + mStreamingBuffer = new StreamingVertexBuffer(mDevice, INITIAL_STREAM_BUFFER_SIZE); +} + +VertexDataManager::~VertexDataManager() +{ + delete mStreamingBuffer; + + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + delete mCurrentValueBuffer[i]; + } +} + +UINT VertexDataManager::writeAttributeData(ArrayVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute) +{ + Buffer *buffer = attribute.mBoundBuffer.get(); + + int inputStride = attribute.stride(); + int elementSize = attribute.typeSize(); + const FormatConverter &converter = formatConverter(attribute); + UINT streamOffset = 0; + + void *output = NULL; + + if (vertexBuffer) + { + output = vertexBuffer->map(attribute, spaceRequired(attribute, count), &streamOffset); + } + + if (output == NULL) + { + ERR("Failed to map vertex buffer."); + return -1; + } + + const char *input = NULL; + + if (buffer) + { + int offset = attribute.mOffset; + + input = static_cast<const char*>(buffer->data()) + offset; + } + else + { + input = static_cast<const char*>(attribute.mPointer); + } + + input += inputStride * start; + + if (converter.identity && inputStride == elementSize) + { + memcpy(output, input, count * inputStride); + } + else + { + converter.convertArray(input, inputStride, count, output); + } + + vertexBuffer->unmap(); + + return streamOffset; +} + +GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *translated) +{ + GLenum error = GL_NO_ERROR; + const VertexAttributeArray &attribs = mContext->getVertexAttributes(); + Program *program = mContext->getCurrentProgram(); + + for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + { + translated[attributeIndex].active = (program->getSemanticIndex(attributeIndex) != -1); + } + + // Determine the required storage size per used buffer + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + Buffer *buffer = attribs[i].mBoundBuffer.get(); + + if (translated[i].active && attribs[i].mArrayEnabled && (buffer || attribs[i].mPointer)) + { + StaticVertexBuffer *staticBuffer = buffer ? buffer->getVertexBuffer() : NULL; + + if (staticBuffer && staticBuffer->size() == 0) + { + int totalCount = buffer->size() / attribs[i].stride(); + staticBuffer->addRequiredSpace(spaceRequired(attribs[i], totalCount)); + } + else if (!staticBuffer || staticBuffer->lookupAttribute(attribs[i]) == -1) + { + if (mStreamingBuffer) + { + mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[i], count)); + } + } + } + } + + // Invalidate static buffers if the attribute formats no longer match + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + Buffer *buffer = attribs[i].mBoundBuffer.get(); + + if (translated[i].active && attribs[i].mArrayEnabled && buffer) + { + StaticVertexBuffer *staticBuffer = buffer->getVertexBuffer(); + + if (staticBuffer && staticBuffer->size() != 0) + { + bool matchingAttributes = true; + + for (int j = 0; j < MAX_VERTEX_ATTRIBS; j++) + { + if (translated[j].active && attribs[j].mArrayEnabled && attribs[j].mBoundBuffer.get() == buffer) + { + if (staticBuffer->lookupAttribute(attribs[j]) == -1) + { + matchingAttributes = false; + break; + } + } + } + + if (!matchingAttributes && mStreamingBuffer) + { + mStreamingBuffer->addRequiredSpaceFor(staticBuffer); + buffer->invalidateStaticData(); + } + } + } + } + + // Reserve the required space per used buffer + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + Buffer *buffer = attribs[i].mBoundBuffer.get(); + + if (translated[i].active && attribs[i].mArrayEnabled && (buffer || attribs[i].mPointer)) + { + ArrayVertexBuffer *staticBuffer = buffer ? buffer->getVertexBuffer() : NULL; + ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : mStreamingBuffer; + + if (vertexBuffer) + { + vertexBuffer->reserveRequiredSpace(); + } + } + } + + // Perform the vertex data translations + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active) + { + Buffer *buffer = attribs[i].mBoundBuffer.get(); + + if (attribs[i].mArrayEnabled) + { + if (!buffer && attribs[i].mPointer == NULL) + { + // This is an application error that would normally result in a crash, but we catch it and return an error + ERR("An enabled vertex array has no buffer and no pointer."); + return GL_INVALID_OPERATION; + } + + const FormatConverter &converter = formatConverter(attribs[i]); + + StaticVertexBuffer *staticBuffer = buffer ? buffer->getVertexBuffer() : NULL; + ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : static_cast<ArrayVertexBuffer*>(mStreamingBuffer); + + UINT streamOffset = -1; + + if (staticBuffer) + { + streamOffset = staticBuffer->lookupAttribute(attribs[i]); + + if (streamOffset == -1) + { + // Convert the entire buffer + int totalCount = buffer->size() / attribs[i].stride(); + int startIndex = attribs[i].mOffset / attribs[i].stride(); + + streamOffset = writeAttributeData(staticBuffer, -startIndex, totalCount, attribs[i]); + } + + if (streamOffset != -1) + { + streamOffset += (start + attribs[i].mOffset / attribs[i].stride()) * converter.outputElementSize; + } + } + else + { + streamOffset = writeAttributeData(mStreamingBuffer, start, count, attribs[i]); + } + + if (streamOffset == -1) + { + return GL_OUT_OF_MEMORY; + } + + translated[i].vertexBuffer = vertexBuffer->getBuffer(); + translated[i].type = converter.d3dDeclType; + translated[i].stride = converter.outputElementSize; + translated[i].offset = streamOffset; + } + else + { + if (mDirtyCurrentValue[i]) + { + delete mCurrentValueBuffer[i]; + mCurrentValueBuffer[i] = new ConstantVertexBuffer(mDevice, attribs[i].mCurrentValue[0], attribs[i].mCurrentValue[1], attribs[i].mCurrentValue[2], attribs[i].mCurrentValue[3]); + mDirtyCurrentValue[i] = false; + } + + translated[i].vertexBuffer = mCurrentValueBuffer[i]->getBuffer(); + + translated[i].type = D3DDECLTYPE_FLOAT4; + translated[i].stride = 0; + translated[i].offset = 0; + } + } + } + + return GL_NO_ERROR; +} + +std::size_t VertexDataManager::spaceRequired(const VertexAttribute &attrib, std::size_t count) const +{ + return formatConverter(attrib).outputElementSize * count; +} + +// 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 }; +}; + +// 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 VertexDataManager::TranslationDescription VertexDataManager::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1] +{ + TRANSLATIONS_FOR_TYPE(GL_BYTE), + TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE), + TRANSLATIONS_FOR_TYPE(GL_SHORT), + TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT), + TRANSLATIONS_FOR_TYPE(GL_FIXED), + TRANSLATIONS_FOR_TYPE(GL_FLOAT) +}; + +void VertexDataManager::checkVertexCaps(DWORD declTypes) +{ + for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++) + { + for (unsigned int j = 0; j < 2; j++) + { + for (unsigned int k = 0; k < 4; k++) + { + if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0) + { + mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion; + } + else + { + mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion; + } + } + } + } +} + +// This is used to index mAttributeTypes and mPossibleTranslations. +unsigned int VertexDataManager::typeIndex(GLenum type) const +{ + switch (type) + { + case GL_BYTE: return 0; + case GL_UNSIGNED_BYTE: return 1; + case GL_SHORT: return 2; + case GL_UNSIGNED_SHORT: return 3; + case GL_FIXED: return 4; + case GL_FLOAT: return 5; + + default: UNREACHABLE(); return 5; + } +} + +void VertexDataManager::setupAttributes(const TranslatedAttribute *attributes) +{ + D3DVERTEXELEMENT9 elements[MAX_VERTEX_ATTRIBS]; + D3DVERTEXELEMENT9 *element = &elements[0]; + + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + if (attributes[i].active) + { + mDevice->SetStreamSource(i, attributes[i].vertexBuffer, attributes[i].offset, attributes[i].stride); + + element->Stream = i; + element->Offset = 0; + element->Type = attributes[i].type; + element->Method = D3DDECLMETHOD_DEFAULT; + element->Usage = D3DDECLUSAGE_TEXCOORD; + element->UsageIndex = attributes[i].semanticIndex; + element++; + } + } + + static const D3DVERTEXELEMENT9 end = D3DDECL_END(); + *element = end; + + IDirect3DVertexDeclaration9 *vertexDeclaration; + mDevice->CreateVertexDeclaration(elements, &vertexDeclaration); + mDevice->SetVertexDeclaration(vertexDeclaration); + vertexDeclaration->Release(); +} + +VertexBuffer::VertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags) : mDevice(device), mVertexBuffer(NULL) +{ + if (size > 0) + { + D3DPOOL pool = getDisplay()->getBufferPool(usageFlags); + HRESULT result = device->CreateVertexBuffer(size, usageFlags, 0, pool, &mVertexBuffer, NULL); + + if (FAILED(result)) + { + ERR("Out of memory allocating a vertex buffer of size %lu.", size); + } + } +} + +VertexBuffer::~VertexBuffer() +{ + if (mVertexBuffer) + { + mVertexBuffer->Release(); + } +} + +void VertexBuffer::unmap() +{ + if (mVertexBuffer) + { + mVertexBuffer->Unlock(); + } +} + +IDirect3DVertexBuffer9 *VertexBuffer::getBuffer() const +{ + return mVertexBuffer; +} + +ConstantVertexBuffer::ConstantVertexBuffer(IDirect3DDevice9 *device, float x, float y, float z, float w) : VertexBuffer(device, 4 * sizeof(float), D3DUSAGE_WRITEONLY) +{ + void *buffer = NULL; + + if (mVertexBuffer) + { + HRESULT result = mVertexBuffer->Lock(0, 0, &buffer, 0); + + if (FAILED(result)) + { + ERR("Lock failed with error 0x%08x", result); + } + } + + if (buffer) + { + float *vector = (float*)buffer; + + vector[0] = x; + vector[1] = y; + vector[2] = z; + vector[3] = w; + + mVertexBuffer->Unlock(); + } +} + +ConstantVertexBuffer::~ConstantVertexBuffer() +{ +} + +ArrayVertexBuffer::ArrayVertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags) : VertexBuffer(device, size, usageFlags) +{ + mBufferSize = size; + mWritePosition = 0; + mRequiredSpace = 0; +} + +ArrayVertexBuffer::~ArrayVertexBuffer() +{ +} + +void ArrayVertexBuffer::addRequiredSpace(UINT requiredSpace) +{ + mRequiredSpace += requiredSpace; +} + +void ArrayVertexBuffer::addRequiredSpaceFor(ArrayVertexBuffer *buffer) +{ + mRequiredSpace += buffer->mRequiredSpace; +} + +StreamingVertexBuffer::StreamingVertexBuffer(IDirect3DDevice9 *device, std::size_t initialSize) : ArrayVertexBuffer(device, initialSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY) +{ +} + +StreamingVertexBuffer::~StreamingVertexBuffer() +{ +} + +void *StreamingVertexBuffer::map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *offset) +{ + void *mapPtr = NULL; + + if (mVertexBuffer) + { + HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE); + + if (FAILED(result)) + { + ERR("Lock failed with error 0x%08x", result); + return NULL; + } + + *offset = mWritePosition; + mWritePosition += requiredSpace; + } + + return mapPtr; +} + +void StreamingVertexBuffer::reserveRequiredSpace() +{ + if (mRequiredSpace > mBufferSize) + { + if (mVertexBuffer) + { + mVertexBuffer->Release(); + mVertexBuffer = NULL; + } + + mBufferSize = std::max(mRequiredSpace, 3 * mBufferSize / 2); // 1.5 x mBufferSize is arbitrary and should be checked to see we don't have too many reallocations. + + D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); + HRESULT result = mDevice->CreateVertexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, pool, &mVertexBuffer, NULL); + + if (FAILED(result)) + { + ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize); + } + + mWritePosition = 0; + } + else if (mWritePosition + mRequiredSpace > mBufferSize) // Recycle + { + if (mVertexBuffer) + { + void *dummy; + mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); + mVertexBuffer->Unlock(); + } + + mWritePosition = 0; + } + + mRequiredSpace = 0; +} + +StaticVertexBuffer::StaticVertexBuffer(IDirect3DDevice9 *device) : ArrayVertexBuffer(device, 0, D3DUSAGE_WRITEONLY) +{ +} + +StaticVertexBuffer::~StaticVertexBuffer() +{ +} + +void *StaticVertexBuffer::map(const VertexAttribute &attribute, std::size_t requiredSpace, UINT *streamOffset) +{ + void *mapPtr = NULL; + + if (mVertexBuffer) + { + HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, 0); + + if (FAILED(result)) + { + ERR("Lock failed with error 0x%08x", result); + return NULL; + } + + int attributeOffset = attribute.mOffset % attribute.stride(); + VertexElement element = {attribute.mType, attribute.mSize, attribute.mNormalized, attributeOffset, mWritePosition}; + mCache.push_back(element); + + *streamOffset = mWritePosition; + mWritePosition += requiredSpace; + } + + return mapPtr; +} + +void StaticVertexBuffer::reserveRequiredSpace() +{ + if (!mVertexBuffer && mBufferSize == 0) + { + D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_WRITEONLY); + HRESULT result = mDevice->CreateVertexBuffer(mRequiredSpace, D3DUSAGE_WRITEONLY, 0, pool, &mVertexBuffer, NULL); + + if (FAILED(result)) + { + ERR("Out of memory allocating a vertex buffer of size %lu.", mRequiredSpace); + } + + mBufferSize = mRequiredSpace; + } + else if (mVertexBuffer && mBufferSize >= mRequiredSpace) + { + // Already allocated + } + else UNREACHABLE(); // Static vertex buffers can't be resized + + mRequiredSpace = 0; +} + +UINT StaticVertexBuffer::lookupAttribute(const VertexAttribute &attribute) +{ + for (unsigned int element = 0; element < mCache.size(); element++) + { + if (mCache[element].type == attribute.mType && mCache[element].size == attribute.mSize && mCache[element].normalized == attribute.mNormalized) + { + if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride()) + { + return mCache[element].streamOffset; + } + } + } + + return -1; +} + +const VertexDataManager::FormatConverter &VertexDataManager::formatConverter(const VertexAttribute &attribute) const +{ + return mAttributeTypes[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1]; +} +} diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.h b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.h new file mode 100644 index 000000000..257f2c309 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.h @@ -0,0 +1,170 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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 <vector> +#include <cstddef> + +#define GL_APICALL +#include <GLES2/gl2.h> + +#include "libGLESv2/Context.h" + +namespace gl +{ + +struct TranslatedAttribute +{ + bool active; + + D3DDECLTYPE type; + UINT offset; + UINT stride; // 0 means not to advance the read pointer at all + UINT semanticIndex; + + IDirect3DVertexBuffer9 *vertexBuffer; +}; + +class VertexBuffer +{ + public: + VertexBuffer(IDirect3DDevice9 *device, UINT size, DWORD usageFlags); + virtual ~VertexBuffer(); + + void unmap(); + + IDirect3DVertexBuffer9 *getBuffer() const; + + protected: + IDirect3DDevice9 *const mDevice; + IDirect3DVertexBuffer9 *mVertexBuffer; + + private: + DISALLOW_COPY_AND_ASSIGN(VertexBuffer); +}; + +class ConstantVertexBuffer : public VertexBuffer +{ + public: + ConstantVertexBuffer(IDirect3DDevice9 *device, float x, float y, float z, float w); + ~ConstantVertexBuffer(); +}; + +class ArrayVertexBuffer : public VertexBuffer +{ + public: + ArrayVertexBuffer(IDirect3DDevice9 *device, UINT size, DWORD usageFlags); + ~ArrayVertexBuffer(); + + UINT size() const { return mBufferSize; } + virtual void *map(const VertexAttribute &attribute, UINT requiredSpace, UINT *streamOffset) = 0; + virtual void reserveRequiredSpace() = 0; + void addRequiredSpace(UINT requiredSpace); + void addRequiredSpaceFor(ArrayVertexBuffer *buffer); + + protected: + UINT mBufferSize; + UINT mWritePosition; + UINT mRequiredSpace; +}; + +class StreamingVertexBuffer : public ArrayVertexBuffer +{ + public: + StreamingVertexBuffer(IDirect3DDevice9 *device, UINT initialSize); + ~StreamingVertexBuffer(); + + void *map(const VertexAttribute &attribute, UINT requiredSpace, UINT *streamOffset); + void reserveRequiredSpace(); +}; + +class StaticVertexBuffer : public ArrayVertexBuffer +{ + public: + explicit StaticVertexBuffer(IDirect3DDevice9 *device); + ~StaticVertexBuffer(); + + void *map(const VertexAttribute &attribute, UINT requiredSpace, UINT *streamOffset); + void reserveRequiredSpace(); + + UINT lookupAttribute(const VertexAttribute &attribute); // Returns the offset into the vertex buffer, or -1 if not found + + private: + struct VertexElement + { + GLenum type; + GLint size; + bool normalized; + int attributeOffset; + + UINT streamOffset; + }; + + std::vector<VertexElement> mCache; +}; + +class VertexDataManager +{ + public: + VertexDataManager(Context *context, IDirect3DDevice9 *backend); + virtual ~VertexDataManager(); + + void dirtyCurrentValue(int index) { mDirtyCurrentValue[index] = true; } + + void setupAttributes(const TranslatedAttribute *attributes); + GLenum prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *outAttribs); + + private: + DISALLOW_COPY_AND_ASSIGN(VertexDataManager); + + UINT spaceRequired(const VertexAttribute &attrib, std::size_t count) const; + UINT writeAttributeData(ArrayVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute); + + Context *const mContext; + IDirect3DDevice9 *const mDevice; + + StreamingVertexBuffer *mStreamingBuffer; + + bool mDirtyCurrentValue[MAX_VERTEX_ATTRIBS]; + ConstantVertexBuffer *mCurrentValueBuffer[MAX_VERTEX_ATTRIBS]; + + // Attribute format conversion + struct FormatConverter + { + bool identity; + std::size_t outputElementSize; + void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out); + D3DDECLTYPE d3dDeclType; + }; + + enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; + + FormatConverter mAttributeTypes[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1] + + struct TranslationDescription + { + DWORD capsFlag; + FormatConverter preferredConversion; + FormatConverter fallbackConversion; + }; + + // This table is used to generate mAttributeTypes. + static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1] + + void checkVertexCaps(DWORD declTypes); + + unsigned int typeIndex(GLenum type) const; + const FormatConverter &formatConverter(const VertexAttribute &attribute) const; +}; + +} + +#endif // LIBGLESV2_GEOMETRY_VERTEXDATAMANAGER_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 000000000..e55dc72ce --- /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 000000000..23957fe6d --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.cpp @@ -0,0 +1,5723 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions. + +#define GL_APICALL +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#include <exception> +#include <limits> + +#include "common/debug.h" +#include "common/version.h" + +#include "libGLESv2/main.h" +#include "libGLESv2/mathutil.h" +#include "libGLESv2/utilities.h" +#include "libGLESv2/Buffer.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/Fence.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Program.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/Shader.h" +#include "libGLESv2/Texture.h" + +bool validImageSize(GLint level, GLsizei width, GLsizei height) +{ + if (level < 0 || width < 0 || height < 0) + { + return false; + } + + if (gl::getContext() && gl::getContext()->supportsNonPower2Texture()) + { + return true; + } + + if (level == 0) + { + return true; + } + + if (gl::isPow2(width) && gl::isPow2(height)) + { + return true; + } + + return false; +} + +extern "C" +{ + +void __stdcall glActiveTexture(GLenum texture) +{ + EVENT("(GLenum texture = 0x%X)", texture); + + try + { + gl::Context *context = gl::getContext(); + + if (context) + { + if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getMaximumCombinedTextureImageUnits() - 1) + { + return error(GL_INVALID_ENUM); + } + + context->setActiveSampler(texture - GL_TEXTURE0); + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glAttachShader(GLuint program, GLuint shader) +{ + EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); + + try + { + gl::Context *context = gl::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) +{ + EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name); + + try + { + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(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) +{ + EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer); + + try + { + if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) + { + return error(GL_INVALID_ENUM); + } + + gl::Context *context = gl::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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha); + + try + { + switch (modeRGB) + { + case GL_FUNC_ADD: + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + break; + default: + return error(GL_INVALID_ENUM); + } + + switch (modeAlpha) + { + case GL_FUNC_ADD: + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + break; + default: + return error(GL_INVALID_ENUM); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)", + srcRGB, dstRGB, srcAlpha, dstAlpha); + + try + { + switch (srcRGB) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + case GL_SRC_ALPHA_SATURATE: + break; + default: + return error(GL_INVALID_ENUM); + } + + switch (dstRGB) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + break; + default: + return error(GL_INVALID_ENUM); + } + + switch (srcAlpha) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + case GL_SRC_ALPHA_SATURATE: + break; + default: + return error(GL_INVALID_ENUM); + } + + switch (dstAlpha) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + break; + default: + return error(GL_INVALID_ENUM); + } + + bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR || + dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR); + + bool constantAlphaUsed = (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA || + dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA); + + if (constantColorUsed && constantAlphaUsed) + { + ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR invalid under WebGL"); + return error(GL_INVALID_OPERATION); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)", + target, size, data, usage); + + try + { + if (size < 0) + { + return error(GL_INVALID_VALUE); + } + + switch (usage) + { + case GL_STREAM_DRAW: + case GL_STATIC_DRAW: + case GL_DYNAMIC_DRAW: + break; + default: + return error(GL_INVALID_ENUM); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)", + target, offset, size, data); + + try + { + if (size < 0 || offset < 0) + { + return error(GL_INVALID_VALUE); + } + + if (data == NULL) + { + return; + } + + gl::Context *context = gl::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) +{ + EVENT("(GLenum target = 0x%X)", target); + + try + { + if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) + { + return error(GL_INVALID_ENUM, 0); + } + + gl::Context *context = gl::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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " + "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", + target, level, internalformat, width, height, border, imageSize, data); + + try + { + if (!validImageSize(level, width, height) || border != 0 || imageSize < 0) + { + return error(GL_INVALID_VALUE); + } + + switch (internalformat) + { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + break; + default: + return error(GL_INVALID_ENUM); + } + + if (border != 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getContext(); + + if (context) + { + if (level > context->getMaximumTextureLevel()) + { + return error(GL_INVALID_VALUE); + } + + switch (target) + { + case GL_TEXTURE_2D: + if (width > (context->getMaximumTextureDimension() >> level) || + height > (context->getMaximumTextureDimension() >> level)) + { + return error(GL_INVALID_VALUE); + } + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + if (width != height) + { + return error(GL_INVALID_VALUE); + } + + if (width > (context->getMaximumCubeTextureDimension() >> level) || + height > (context->getMaximumCubeTextureDimension() >> level)) + { + return error(GL_INVALID_VALUE); + } + break; + default: + return error(GL_INVALID_ENUM); + } + + 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) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, " + "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", + target, level, xoffset, yoffset, width, height, format, imageSize, data); + + try + { + if (!gl::IsTextureTarget(target)) + { + return error(GL_INVALID_ENUM); + } + + if (xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0) + { + return error(GL_INVALID_VALUE); + } + + switch (format) + { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + break; + default: + return error(GL_INVALID_ENUM); + } + + if (width == 0 || height == 0 || data == NULL) + { + return; + } + + gl::Context *context = gl::getContext(); + + if (context) + { + if (level > context->getMaximumTextureLevel()) + { + return error(GL_INVALID_VALUE); + } + + 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) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, " + "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)", + target, level, internalformat, x, y, width, height, border); + + try + { + if (!validImageSize(level, width, height)) + { + return error(GL_INVALID_VALUE); + } + + if (border != 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getContext(); + + if (context) + { + switch (target) + { + case GL_TEXTURE_2D: + if (width > (context->getMaximumTextureDimension() >> level) || + height > (context->getMaximumTextureDimension() >> level)) + { + return error(GL_INVALID_VALUE); + } + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + if (width != height) + { + return error(GL_INVALID_VALUE); + } + + if (width > (context->getMaximumCubeTextureDimension() >> level) || + height > (context->getMaximumCubeTextureDimension() >> level)) + { + return error(GL_INVALID_VALUE); + } + break; + default: + return error(GL_INVALID_ENUM); + } + + gl::Framebuffer *framebuffer = context->getReadFramebuffer(); + + if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) + { + return error(GL_INVALID_FRAMEBUFFER_OPERATION); + } + + if (context->getReadFramebufferHandle() != 0 && framebuffer->getColorbuffer()->getSamples() != 0) + { + return error(GL_INVALID_OPERATION); + } + + gl::Colorbuffer *source = framebuffer->getColorbuffer(); + GLenum colorbufferFormat = source->getInternalFormat(); + + // [OpenGL ES 2.0.24] table 3.9 + switch (internalformat) + { + case GL_ALPHA: + if (colorbufferFormat != GL_ALPHA && + colorbufferFormat != GL_RGBA && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES) + { + return error(GL_INVALID_OPERATION); + } + break; + case GL_LUMINANCE: + case GL_RGB: + if (colorbufferFormat != GL_RGB && + colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES) + { + return error(GL_INVALID_OPERATION); + } + break; + case GL_LUMINANCE_ALPHA: + case GL_RGBA: + if (colorbufferFormat != GL_RGBA && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES) + { + return error(GL_INVALID_OPERATION); + } + break; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + if (context->supportsCompressedTextures()) + { + return error(GL_INVALID_OPERATION); + } + else + { + return error(GL_INVALID_ENUM); + } + break; + default: + return error(GL_INVALID_ENUM); + } + + if (target == GL_TEXTURE_2D) + { + gl::Texture2D *texture = context->getTexture2D(); + + if (!texture) + { + return error(GL_INVALID_OPERATION); + } + + texture->copyImage(level, internalformat, x, y, width, height, framebuffer); + } + else if (gl::IsCubemapTextureTarget(target)) + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + + if (!texture) + { + return error(GL_INVALID_OPERATION); + } + + texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer); + } + else UNREACHABLE(); + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", + target, level, xoffset, yoffset, x, y, width, height); + + try + { + if (!gl::IsTextureTarget(target)) + { + return error(GL_INVALID_ENUM); + } + + if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) + { + return error(GL_INVALID_VALUE); + } + + if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height) + { + return error(GL_INVALID_VALUE); + } + + if (width == 0 || height == 0) + { + return; + } + + gl::Context *context = gl::getContext(); + + if (context) + { + if (level > context->getMaximumTextureLevel()) + { + return error(GL_INVALID_VALUE); + } + + gl::Framebuffer *framebuffer = context->getReadFramebuffer(); + + if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) + { + return error(GL_INVALID_FRAMEBUFFER_OPERATION); + } + + if (context->getReadFramebufferHandle() != 0 && framebuffer->getColorbuffer()->getSamples() != 0) + { + return error(GL_INVALID_OPERATION); + } + + gl::Colorbuffer *source = framebuffer->getColorbuffer(); + GLenum colorbufferFormat = source->getInternalFormat(); + gl::Texture *texture = NULL; + + if (target == GL_TEXTURE_2D) + { + texture = context->getTexture2D(); + } + else if (gl::IsCubemapTextureTarget(target)) + { + texture = context->getTextureCubeMap(); + } + else UNREACHABLE(); + + if (!texture) + { + return error(GL_INVALID_OPERATION); + } + + GLenum textureFormat = texture->getInternalFormat(); + + // [OpenGL ES 2.0.24] table 3.9 + switch (textureFormat) + { + case GL_ALPHA: + if (colorbufferFormat != GL_ALPHA && + colorbufferFormat != GL_RGBA && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES) + { + return error(GL_INVALID_OPERATION); + } + break; + case GL_LUMINANCE: + case GL_RGB: + if (colorbufferFormat != GL_RGB && + colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES) + { + return error(GL_INVALID_OPERATION); + } + break; + case GL_LUMINANCE_ALPHA: + case GL_RGBA: + if (colorbufferFormat != GL_RGBA && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES) + { + return error(GL_INVALID_OPERATION); + } + break; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + return error(GL_INVALID_OPERATION); + default: + return error(GL_INVALID_OPERATION); + } + + texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, framebuffer); + } + } + + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +GLuint __stdcall glCreateProgram(void) +{ + EVENT("()"); + + try + { + gl::Context *context = gl::getContext(); + + if (context) + { + return context->createProgram(); + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY, 0); + } + + return 0; +} + +GLuint __stdcall glCreateShader(GLenum type) +{ + EVENT("(GLenum type = 0x%X)", type); + + try + { + gl::Context *context = gl::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) +{ + EVENT("(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) +{ + EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers); + + try + { + if (n < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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 glDeleteFencesNV(GLsizei n, const GLuint* fences) +{ + EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences); + + try + { + if (n < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getContext(); + + if (context) + { + for (int i = 0; i < n; i++) + { + context->deleteFence(fences[i]); + } + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) +{ + EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers); + + try + { + if (n < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(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) +{ + EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); + + try + { + if (n < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(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) +{ + EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures); + + try + { + if (n < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLenum func = 0x%X)", func); + + try + { + switch (func) + { + case GL_NEVER: + case GL_ALWAYS: + case GL_LESS: + case GL_LEQUAL: + case GL_EQUAL: + case GL_GREATER: + case GL_GEQUAL: + case GL_NOTEQUAL: + break; + default: + return error(GL_INVALID_ENUM); + } + + gl::Context *context = gl::getContext(); + + if (context) + { + context->setDepthFunc(func); + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glDepthMask(GLboolean flag) +{ + EVENT("(GLboolean flag = %d)", flag); + + try + { + gl::Context *context = gl::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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(GLuint index = %d)", index); + + try + { + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getContext(); + + if (context) + { + context->setEnableVertexAttribArray(index, false); + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count) +{ + EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count); + + try + { + if (count < 0 || first < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)", + mode, count, type, indices); + + try + { + if (count < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getContext(); + + if (context) + { + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT: + break; + case GL_UNSIGNED_INT: + if (!context->supports32bitIndices()) + { + return error(GL_INVALID_ENUM); + } + break; + default: + return error(GL_INVALID_ENUM); + } + + context->drawElements(mode, count, type, indices); + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glEnable(GLenum cap) +{ + EVENT("(GLenum cap = 0x%X)", cap); + + try + { + gl::Context *context = gl::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) +{ + EVENT("(GLuint index = %d)", index); + + try + { + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getContext(); + + if (context) + { + context->setEnableVertexAttribArray(index, true); + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glFinishFenceNV(GLuint fence) +{ + EVENT("(GLuint fence = %d)", fence); + + try + { + gl::Context *context = gl::getContext(); + + if (context) + { + gl::Fence* fenceObject = context->getFence(fence); + + if (fenceObject == NULL) + { + return error(GL_INVALID_OPERATION); + } + + fenceObject->finishFence(); + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glFinish(void) +{ + EVENT("()"); + + try + { + gl::Context *context = gl::getContext(); + + if (context) + { + context->finish(); + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glFlush(void) +{ + EVENT("()"); + + 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) +{ + EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, " + "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer); + + try + { + if ((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) + || renderbuffertarget != GL_RENDERBUFFER) + { + 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) +{ + EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, " + "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level); + + try + { + if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) + { + return error(GL_INVALID_ENUM); + } + + switch (attachment) + { + case GL_COLOR_ATTACHMENT0: + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + break; + default: + return error(GL_INVALID_ENUM); + } + + gl::Context *context = gl::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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(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 glGenFencesNV(GLsizei n, GLuint* fences) +{ + EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences); + + try + { + if (n < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getContext(); + + if (context) + { + for (int i = 0; i < n; i++) + { + fences[i] = context->createFence(); + } + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers) +{ + EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers); + + try + { + if (n < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, " + "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)", + program, index, bufsize, length, size, type, name); + + try + { + if (bufsize < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, " + "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)", + program, index, bufsize, length, size, type, name); + + try + { + if (bufsize < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)", + program, maxcount, count, shaders); + + try + { + if (maxcount < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("()"); + + gl::Context *context = gl::getContext(); + + if (context) + { + return context->getError(); + } + + return GL_NO_ERROR; +} + +void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) +{ + EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params); + + try + { + + gl::Context *context = gl::getContext(); + + if (context) + { + gl::Fence *fenceObject = context->getFence(fence); + + if (fenceObject == NULL) + { + return error(GL_INVALID_OPERATION); + } + + fenceObject->getFenceiv(pname, params); + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glGetFloatv(GLenum pname, GLfloat* params) +{ + EVENT("(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) +{ + EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", + target, attachment, pname, params); + + try + { + gl::Context *context = gl::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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", + program, bufsize, length, infolog); + + try + { + if (bufsize < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(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->getInternalFormat(); break; + case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break; + case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break; + case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break; + case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break; + case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break; + case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break; + case GL_RENDERBUFFER_SAMPLES_ANGLE: + if (context->getMaxSupportedSamples() != 0) + { + *params = renderbuffer->getSamples(); + } + else + { + return error(GL_INVALID_ENUM); + } + break; + default: + return error(GL_INVALID_ENUM); + } + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params) +{ + EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params); + + try + { + gl::Context *context = gl::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) +{ + EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", + shader, bufsize, length, infolog); + + try + { + if (bufsize < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)", + shadertype, precisiontype, range, precision); + + try + { + switch (shadertype) + { + case GL_VERTEX_SHADER: + case GL_FRAGMENT_SHADER: + break; + default: + return error(GL_INVALID_ENUM); + } + + switch (precisiontype) + { + case GL_LOW_FLOAT: + case GL_MEDIUM_FLOAT: + case GL_HIGH_FLOAT: + // Assume IEEE 754 precision + range[0] = 127; + range[1] = 127; + *precision = 23; + break; + case GL_LOW_INT: + case GL_MEDIUM_INT: + case GL_HIGH_INT: + // Some (most) hardware only supports single-precision floating-point numbers, + // which can accurately represent integers up to +/-16777216 + range[0] = 24; + range[1] = 24; + *precision = 0; + break; + default: + return error(GL_INVALID_ENUM); + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) +{ + EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)", + shader, bufsize, length, source); + + try + { + if (bufsize < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLenum name = 0x%X)", name); + + try + { + gl::Context *context = gl::getContext(); + + switch (name) + { + case GL_VENDOR: + return (GLubyte*)"Google Inc."; + case GL_RENDERER: + return (GLubyte*)"ANGLE"; + case GL_VERSION: + return (GLubyte*)"OpenGL ES 2.0 (ANGLE "VERSION_STRING")"; + case GL_SHADING_LANGUAGE_VERSION: + return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE "VERSION_STRING")"; + case GL_EXTENSIONS: + return (GLubyte*)((context != NULL) ? context->getExtensionString() : ""); + default: + return error(GL_INVALID_ENUM, (GLubyte*)NULL); + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY, (GLubyte*)NULL); + } + + return NULL; +} + +void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params); + + try + { + gl::Context *context = gl::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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params); + + try + { + gl::Context *context = gl::getContext(); + + if (context) + { + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return error(GL_INVALID_VALUE); + } + + const gl::VertexAttribute &attribState = context->getVertexAttribState(index); + + switch (pname) + { + case GL_VERTEX_ATTRIB_ARRAY_ENABLED: + *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE); + break; + case GL_VERTEX_ATTRIB_ARRAY_SIZE: + *params = (GLfloat)attribState.mSize; + break; + case GL_VERTEX_ATTRIB_ARRAY_STRIDE: + *params = (GLfloat)attribState.mStride; + break; + case GL_VERTEX_ATTRIB_ARRAY_TYPE: + *params = (GLfloat)attribState.mType; + break; + case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: + *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE); + break; + case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: + *params = (GLfloat)attribState.mBoundBuffer.id(); + break; + case GL_CURRENT_VERTEX_ATTRIB: + for (int i = 0; i < 4; ++i) + { + params[i] = attribState.mCurrentValue[i]; + } + break; + default: return error(GL_INVALID_ENUM); + } + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) +{ + EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params); + + try + { + gl::Context *context = gl::getContext(); + + if (context) + { + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return error(GL_INVALID_VALUE); + } + + const gl::VertexAttribute &attribState = context->getVertexAttribState(index); + + switch (pname) + { + case GL_VERTEX_ATTRIB_ARRAY_ENABLED: + *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE); + break; + case GL_VERTEX_ATTRIB_ARRAY_SIZE: + *params = attribState.mSize; + break; + case GL_VERTEX_ATTRIB_ARRAY_STRIDE: + *params = attribState.mStride; + break; + case GL_VERTEX_ATTRIB_ARRAY_TYPE: + *params = attribState.mType; + break; + case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: + *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE); + break; + case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: + *params = attribState.mBoundBuffer.id(); + break; + case GL_CURRENT_VERTEX_ATTRIB: + for (int i = 0; i < 4; ++i) + { + float currentValue = attribState.mCurrentValue[i]; + params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f)); + } + break; + default: return error(GL_INVALID_ENUM); + } + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer) +{ + EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer); + + try + { + gl::Context *context = gl::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) +{ + EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode); + + try + { + switch (mode) + { + case GL_FASTEST: + case GL_NICEST: + case GL_DONT_CARE: + break; + default: + return error(GL_INVALID_ENUM); + } + + gl::Context *context = gl::getContext(); + switch (target) + { + case GL_GENERATE_MIPMAP_HINT: + if (context) context->setGenerateMipmapHint(mode); + break; + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: + if (context) context->setFragmentShaderDerivativeHint(mode); + break; + default: + return error(GL_INVALID_ENUM); + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +GLboolean __stdcall glIsBuffer(GLuint buffer) +{ + EVENT("(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) +{ + EVENT("(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 glIsFenceNV(GLuint fence) +{ + EVENT("(GLuint fence = %d)", fence); + + try + { + gl::Context *context = gl::getContext(); + + if (context) + { + gl::Fence *fenceObject = context->getFence(fence); + + if (fenceObject == NULL) + { + return GL_FALSE; + } + + return fenceObject->isFence(); + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY, GL_FALSE); + } + + return GL_FALSE; +} + +GLboolean __stdcall glIsFramebuffer(GLuint framebuffer) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, " + "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)", + x, y, width, height, format, type, pixels); + + try + { + if (width < 0 || height < 0) + { + return error(GL_INVALID_VALUE); + } + + 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) +{ + EVENT("()"); + + try + { + gl::Shader::releaseCompiler(); + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, samples, internalformat, width, height); + + try + { + switch (target) + { + case GL_RENDERBUFFER: + break; + default: + return error(GL_INVALID_ENUM); + } + + if (!gl::IsColorRenderable(internalformat) && !gl::IsDepthRenderable(internalformat) && !gl::IsStencilRenderable(internalformat)) + { + return error(GL_INVALID_ENUM); + } + + if (width < 0 || height < 0 || samples < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getContext(); + + if (context) + { + if (width > context->getMaximumRenderbufferDimension() || + height > context->getMaximumRenderbufferDimension() || + samples > context->getMaxSupportedSamples()) + { + return error(GL_INVALID_VALUE); + } + + GLuint handle = context->getRenderbufferHandle(); + if (handle == 0) + { + return error(GL_INVALID_OPERATION); + } + + switch (internalformat) + { + case GL_DEPTH_COMPONENT16: + context->setRenderbufferStorage(new gl::Depthbuffer(width, height, samples)); + break; + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGB565: + case GL_RGB8_OES: + case GL_RGBA8_OES: + context->setRenderbufferStorage(new gl::Colorbuffer(width, height, internalformat, samples)); + break; + case GL_STENCIL_INDEX8: + context->setRenderbufferStorage(new gl::Stencilbuffer(width, height, samples)); + break; + case GL_DEPTH24_STENCIL8_OES: + context->setRenderbufferStorage(new gl::DepthStencilbuffer(width, height, samples)); + break; + default: + return error(GL_INVALID_ENUM); + } + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ + glRenderbufferStorageMultisampleANGLE(target, 0, internalformat, width, height); +} + +void __stdcall glSampleCoverage(GLclampf value, GLboolean invert) +{ + EVENT("(GLclampf value = %f, GLboolean invert = %d)", value, invert); + + try + { + gl::Context* context = gl::getContext(); + + if (context) + { + context->setSampleCoverageParams(gl::clamp01(value), invert == GL_TRUE); + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glSetFenceNV(GLuint fence, GLenum condition) +{ + EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition); + + try + { + if (condition != GL_ALL_COMPLETED_NV) + { + return error(GL_INVALID_ENUM); + } + + gl::Context *context = gl::getContext(); + + if (context) + { + gl::Fence *fenceObject = context->getFence(fence); + + if (fenceObject == NULL) + { + return error(GL_INVALID_OPERATION); + } + + fenceObject->setFence(condition); + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height) +{ + EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); + + try + { + if (width < 0 || height < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context* context = gl::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) +{ + EVENT("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, " + "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", + n, shaders, binaryformat, binary, length); + + try + { + // No binary shader formats are supported. + return error(GL_INVALID_ENUM); + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar** string, const GLint* length) +{ + EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)", + shader, count, string, length); + + try + { + if (count < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask); + + try + { + switch (face) + { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + default: + return error(GL_INVALID_ENUM); + } + + switch (func) + { + case GL_NEVER: + case GL_ALWAYS: + case GL_LESS: + case GL_LEQUAL: + case GL_EQUAL: + case GL_GEQUAL: + case GL_GREATER: + case GL_NOTEQUAL: + break; + default: + return error(GL_INVALID_ENUM); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask); + + try + { + switch (face) + { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + default: + return error(GL_INVALID_ENUM); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)", + face, fail, zfail, zpass); + + try + { + switch (face) + { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + default: + return error(GL_INVALID_ENUM); + } + + switch (fail) + { + case GL_ZERO: + case GL_KEEP: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP: + case GL_DECR_WRAP: + break; + default: + return error(GL_INVALID_ENUM); + } + + switch (zfail) + { + case GL_ZERO: + case GL_KEEP: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP: + case GL_DECR_WRAP: + break; + default: + return error(GL_INVALID_ENUM); + } + + switch (zpass) + { + case GL_ZERO: + case GL_KEEP: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP: + case GL_DECR_WRAP: + break; + default: + return error(GL_INVALID_ENUM); + } + + gl::Context *context = gl::getContext(); + + if (context) + { + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) + { + context->setStencilOperations(fail, zfail, zpass); + } + + if (face == GL_BACK || face == GL_FRONT_AND_BACK) + { + context->setStencilBackOperations(fail, zfail, zpass); + } + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +GLboolean __stdcall glTestFenceNV(GLuint fence) +{ + EVENT("(GLuint fence = %d)", fence); + + try + { + gl::Context *context = gl::getContext(); + + if (context) + { + gl::Fence *fenceObject = context->getFence(fence); + + if (fenceObject == NULL) + { + return error(GL_INVALID_OPERATION, GL_TRUE); + } + + return fenceObject->testFence(); + } + } + catch(std::bad_alloc&) + { + error(GL_OUT_OF_MEMORY); + } + + return GL_TRUE; +} + +void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, const GLvoid* pixels) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, " + "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", + target, level, internalformat, width, height, border, format, type, pixels); + + try + { + if (!validImageSize(level, width, height)) + { + return error(GL_INVALID_VALUE); + } + + if (internalformat != format) + { + return error(GL_INVALID_OPERATION); + } + + switch (format) + { + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_FLOAT: + case GL_HALF_FLOAT_OES: + break; + default: + return error(GL_INVALID_ENUM); + } + break; + case GL_RGB: + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_FLOAT: + case GL_HALF_FLOAT_OES: + break; + default: + return error(GL_INVALID_ENUM); + } + break; + case GL_RGBA: + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_FLOAT: + case GL_HALF_FLOAT_OES: + break; + default: + return error(GL_INVALID_ENUM); + } + break; + case GL_BGRA_EXT: + switch (type) + { + case GL_UNSIGNED_BYTE: + break; + default: + return error(GL_INVALID_ENUM); + } + break; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + break; + default: + return error(GL_INVALID_VALUE); + } + + if (border != 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getContext(); + + if (context) + { + switch (target) + { + case GL_TEXTURE_2D: + if (width > (context->getMaximumTextureDimension() >> level) || + height > (context->getMaximumTextureDimension() >> level)) + { + return error(GL_INVALID_VALUE); + } + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + if (width != height) + { + return error(GL_INVALID_VALUE); + } + + if (width > (context->getMaximumCubeTextureDimension() >> level) || + height > (context->getMaximumCubeTextureDimension() >> level)) + { + return error(GL_INVALID_VALUE); + } + break; + default: + return error(GL_INVALID_ENUM); + } + + if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || + format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) + { + if (context->supportsCompressedTextures()) + { + return error(GL_INVALID_OPERATION); + } + else + { + return error(GL_INVALID_ENUM); + } + } + + if (type == GL_FLOAT) + { + if (!context->supportsFloatTextures()) + { + return error(GL_INVALID_ENUM); + } + } + else if (type == GL_HALF_FLOAT_OES) + { + if (!context->supportsHalfFloatTextures()) + { + return error(GL_INVALID_ENUM); + } + } + + if (target == GL_TEXTURE_2D) + { + gl::Texture2D *texture = context->getTexture2D(); + + if (!texture) + { + return error(GL_INVALID_OPERATION); + } + + texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels); + } + else + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + + if (!texture) + { + return error(GL_INVALID_OPERATION); + } + + switch (target) + { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + texture->setImagePosX(level, width, height, format, type, context->getUnpackAlignment(), pixels); + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + texture->setImageNegX(level, width, height, format, type, context->getUnpackAlignment(), pixels); + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + texture->setImagePosY(level, width, height, format, type, context->getUnpackAlignment(), pixels); + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + texture->setImageNegY(level, width, height, format, type, context->getUnpackAlignment(), pixels); + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + texture->setImagePosZ(level, width, height, format, type, context->getUnpackAlignment(), pixels); + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + texture->setImageNegZ(level, width, height, format, type, context->getUnpackAlignment(), pixels); + break; + default: UNREACHABLE(); + } + } + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param) +{ + 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) +{ + EVENT("(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) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, " + "const GLvoid* pixels = 0x%0.8p)", + target, level, xoffset, yoffset, width, height, format, type, pixels); + + try + { + if (!gl::IsTextureTarget(target)) + { + return error(GL_INVALID_ENUM); + } + + if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) + { + return error(GL_INVALID_VALUE); + } + + if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height) + { + return error(GL_INVALID_VALUE); + } + + if (!gl::CheckTextureFormatType(format, type)) + { + return error(GL_INVALID_ENUM); + } + + if (width == 0 || height == 0 || pixels == NULL) + { + return; + } + + gl::Context *context = gl::getContext(); + + if (context) + { + if (level > context->getMaximumTextureLevel()) + { + return error(GL_INVALID_VALUE); + } + + if (format == GL_FLOAT) + { + if (!context->supportsFloatTextures()) + { + return error(GL_INVALID_ENUM); + } + } + else if (format == GL_HALF_FLOAT_OES) + { + if (!context->supportsHalfFloatTextures()) + { + return error(GL_INVALID_ENUM); + } + } + + 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 (format != texture->getInternalFormat()) + { + 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); + } + + texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels); + } + else + { + UNREACHABLE(); + } + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glUniform1f(GLint location, GLfloat x) +{ + glUniform1fv(location, 1, &x); +} + +void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + + try + { + if (count < 0) + { + return error(GL_INVALID_VALUE); + } + + if (location == -1) + { + return; + } + + gl::Context *context = gl::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) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + + try + { + if (count < 0) + { + return error(GL_INVALID_VALUE); + } + + if (location == -1) + { + return; + } + + gl::Context *context = gl::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) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + + try + { + if (count < 0) + { + return error(GL_INVALID_VALUE); + } + + if (location == -1) + { + return; + } + + gl::Context *context = gl::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) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + + try + { + if (count < 0) + { + return error(GL_INVALID_VALUE); + } + + if (location == -1) + { + return; + } + + gl::Context *context = gl::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) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + + try + { + if (count < 0) + { + return error(GL_INVALID_VALUE); + } + + if (location == -1) + { + return; + } + + gl::Context *context = gl::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) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + + try + { + if (count < 0) + { + return error(GL_INVALID_VALUE); + } + + if (location == -1) + { + return; + } + + gl::Context *context = gl::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) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + + try + { + if (count < 0) + { + return error(GL_INVALID_VALUE); + } + + if (location == -1) + { + return; + } + + gl::Context *context = gl::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) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + + try + { + if (count < 0) + { + return error(GL_INVALID_VALUE); + } + + if (location == -1) + { + return; + } + + gl::Context *context = gl::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) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + try + { + if (count < 0 || transpose != GL_FALSE) + { + return error(GL_INVALID_VALUE); + } + + if (location == -1) + { + return; + } + + gl::Context *context = gl::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) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + try + { + if (count < 0 || transpose != GL_FALSE) + { + return error(GL_INVALID_VALUE); + } + + if (location == -1) + { + return; + } + + gl::Context *context = gl::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) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + try + { + if (count < 0 || transpose != GL_FALSE) + { + return error(GL_INVALID_VALUE); + } + + if (location == -1) + { + return; + } + + gl::Context *context = gl::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) +{ + EVENT("(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) +{ + EVENT("(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) +{ + EVENT("(GLuint index = %d, GLfloat x = %f)", index, x); + + try + { + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + + try + { + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y); + + try + { + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + + try + { + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z); + + try + { + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + + try + { + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w); + + try + { + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + + try + { + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, " + "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)", + index, size, type, normalized, stride, ptr); + + try + { + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return error(GL_INVALID_VALUE); + } + + if (size < 1 || size > 4) + { + return error(GL_INVALID_VALUE); + } + + switch (type) + { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_FIXED: + case GL_FLOAT: + break; + default: + return error(GL_INVALID_ENUM); + } + + if (stride < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); + + try + { + if (width < 0 || height < 0) + { + return error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, " + "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, " + "GLbitfield mask = 0x%X, GLenum filter = 0x%X)", + srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter); + + try + { + switch (filter) + { + case GL_NEAREST: + break; + default: + return error(GL_INVALID_ENUM); + } + + if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0) + { + return error(GL_INVALID_VALUE); + } + + if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0) + { + ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation"); + return error(GL_INVALID_OPERATION); + } + + gl::Context *context = gl::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) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, " + "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, " + "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)", + target, level, internalformat, width, height, depth, border, format, type, pixels); + + try + { + UNIMPLEMENTED(); // FIXME + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname) +{ + struct Extension + { + const char *name; + __eglMustCastToProperFunctionPointerType address; + }; + + static const Extension glExtensions[] = + { + {"glTexImage3DOES", (__eglMustCastToProperFunctionPointerType)glTexImage3DOES}, + {"glBlitFramebufferANGLE", (__eglMustCastToProperFunctionPointerType)glBlitFramebufferANGLE}, + {"glRenderbufferStorageMultisampleANGLE", (__eglMustCastToProperFunctionPointerType)glRenderbufferStorageMultisampleANGLE}, + {"glDeleteFencesNV", (__eglMustCastToProperFunctionPointerType)glDeleteFencesNV}, + {"glGenFencesNV", (__eglMustCastToProperFunctionPointerType)glGenFencesNV}, + {"glIsFenceNV", (__eglMustCastToProperFunctionPointerType)glIsFenceNV}, + {"glTestFenceNV", (__eglMustCastToProperFunctionPointerType)glTestFenceNV}, + {"glGetFenceivNV", (__eglMustCastToProperFunctionPointerType)glGetFenceivNV}, + {"glFinishFenceNV", (__eglMustCastToProperFunctionPointerType)glFinishFenceNV}, + {"glSetFenceNV", (__eglMustCastToProperFunctionPointerType)glSetFenceNV}, + }; + + for (int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++) + { + if (strcmp(procname, glExtensions[ext].name) == 0) + { + return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address; + } + } + + return NULL; +} + +void __stdcall glBindTexImage(egl::Surface *surface) +{ + EVENT("(egl::Surface* surface = 0x%0.8p)", + surface); + + try + { + gl::Context *context = gl::getContext(); + + if (context) + { + gl::Texture2D *textureObject = context->getTexture2D(); + + if (textureObject) + { + textureObject->bindTexImage(surface); + } + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +} diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.def b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.def new file mode 100644 index 000000000..b91217199 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.def @@ -0,0 +1,164 @@ +LIBRARY libGLESv2 +EXPORTS + glActiveTexture @1 + glAttachShader @2 + glBindAttribLocation @3 + glBindBuffer @4 + glBindFramebuffer @5 + glBindRenderbuffer @6 + glBindTexture @7 + glBlendColor @8 + glBlendEquation @9 + glBlendEquationSeparate @10 + glBlendFunc @11 + glBlendFuncSeparate @12 + glBufferData @13 + glBufferSubData @14 + glCheckFramebufferStatus @15 + glClear @16 + glClearColor @17 + glClearDepthf @18 + glClearStencil @19 + glColorMask @20 + glCompileShader @21 + glCompressedTexImage2D @22 + glCompressedTexSubImage2D @23 + glCopyTexImage2D @24 + glCopyTexSubImage2D @25 + glCreateProgram @26 + glCreateShader @27 + glCullFace @28 + glDeleteBuffers @29 + glDeleteFramebuffers @30 + glDeleteProgram @32 + glDeleteRenderbuffers @33 + glDeleteShader @34 + glDeleteTextures @31 + glDepthFunc @36 + glDepthMask @37 + glDepthRangef @38 + glDetachShader @35 + glDisable @39 + glDisableVertexAttribArray @40 + glDrawArrays @41 + glDrawElements @42 + glEnable @43 + glEnableVertexAttribArray @44 + glFinish @45 + glFlush @46 + glFramebufferRenderbuffer @47 + glFramebufferTexture2D @48 + glFrontFace @49 + glGenBuffers @50 + glGenFramebuffers @52 + glGenRenderbuffers @53 + glGenTextures @54 + glGenerateMipmap @51 + glGetActiveAttrib @55 + glGetActiveUniform @56 + glGetAttachedShaders @57 + glGetAttribLocation @58 + glGetBooleanv @59 + glGetBufferParameteriv @60 + glGetError @61 + glGetFloatv @62 + glGetFramebufferAttachmentParameteriv @63 + glGetIntegerv @64 + glGetProgramInfoLog @66 + glGetProgramiv @65 + glGetRenderbufferParameteriv @67 + glGetShaderInfoLog @69 + glGetShaderPrecisionFormat @70 + glGetShaderSource @71 + glGetShaderiv @68 + glGetString @72 + glGetTexParameterfv @73 + glGetTexParameteriv @74 + glGetUniformLocation @77 + glGetUniformfv @75 + glGetUniformiv @76 + glGetVertexAttribPointerv @80 + glGetVertexAttribfv @78 + glGetVertexAttribiv @79 + glHint @81 + glIsBuffer @82 + glIsEnabled @83 + glIsFramebuffer @84 + glIsProgram @85 + glIsRenderbuffer @86 + glIsShader @87 + glIsTexture @88 + glLineWidth @89 + glLinkProgram @90 + glPixelStorei @91 + glPolygonOffset @92 + glReadPixels @93 + glReleaseShaderCompiler @94 + glRenderbufferStorage @95 + glSampleCoverage @96 + glScissor @97 + glShaderBinary @98 + glShaderSource @99 + glStencilFunc @100 + glStencilFuncSeparate @101 + glStencilMask @102 + glStencilMaskSeparate @103 + glStencilOp @104 + glStencilOpSeparate @105 + glTexImage2D @106 + glTexParameterf @107 + glTexParameterfv @108 + glTexParameteri @109 + glTexParameteriv @110 + glTexSubImage2D @111 + glUniform1f @112 + glUniform1fv @113 + glUniform1i @114 + glUniform1iv @115 + glUniform2f @116 + glUniform2fv @117 + glUniform2i @118 + glUniform2iv @119 + glUniform3f @120 + glUniform3fv @121 + glUniform3i @122 + glUniform3iv @123 + glUniform4f @124 + glUniform4fv @125 + glUniform4i @126 + glUniform4iv @127 + glUniformMatrix2fv @128 + glUniformMatrix3fv @129 + glUniformMatrix4fv @130 + glUseProgram @131 + glValidateProgram @132 + glVertexAttrib1f @133 + glVertexAttrib1fv @134 + glVertexAttrib2f @135 + glVertexAttrib2fv @136 + glVertexAttrib3f @137 + glVertexAttrib3fv @138 + glVertexAttrib4f @139 + glVertexAttrib4fv @140 + glVertexAttribPointer @141 + glViewport @142 + + ; Extensions + glTexImage3DOES @143 + glBlitFramebufferANGLE @149 + glRenderbufferStorageMultisampleANGLE @150 + glDeleteFencesNV @151 + glFinishFenceNV @152 + glGenFencesNV @153 + glGetFenceivNV @154 + glIsFenceNV @155 + glSetFenceNV @156 + glTestFenceNV @157 + + ; EGL dependencies + glCreateContext @144 NONAME + glDestroyContext @145 NONAME + glMakeCurrent @146 NONAME + glGetCurrentContext @147 NONAME + glGetProcAddress @148 NONAME + glBindTexImage @158 NONAME diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.rc b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.rc new file mode 100644 index 000000000..4e733bdaf --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.rc @@ -0,0 +1,102 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" +#include "../common/version.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "#include ""../common/version.h""\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION + PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "ANGLE libGLESv2 Dynamic Link Library" + VALUE "FileVersion", VERSION_STRING + VALUE "InternalName", "libGLESv2" + VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc." + VALUE "OriginalFilename", "libGLESv2.dll" + VALUE "PrivateBuild", VERSION_STRING + VALUE "ProductName", "ANGLE libGLESv2 Dynamic Link Library" + VALUE "ProductVersion", VERSION_STRING + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.vcproj b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.vcproj new file mode 100644 index 000000000..5bb2e68a9 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.vcproj @@ -0,0 +1,369 @@ +<?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="d3d9.lib D3dx9.lib d3dcompiler.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
mkdir "$(ProjectDir)..\..\lib\$(ConfigurationName)\"
copy "$(OutDir)\libGLESv2.dll" "$(ProjectDir)..\..\lib\$(ConfigurationName)\"
copy "$(OutDir)\libGLESv2.lib" "$(ProjectDir)..\..\lib\$(ConfigurationName)\"
@echo off
" + /> + </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="d3d9.lib D3dx9.lib d3dcompiler.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
mkdir "$(ProjectDir)..\..\lib\$(ConfigurationName)\"
copy "$(OutDir)\libGLESv2.dll" "$(ProjectDir)..\..\lib\$(ConfigurationName)\"
copy "$(OutDir)\libGLESv2.lib" "$(ProjectDir)..\..\lib\$(ConfigurationName)\"
@echo off
" + /> + </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=".\Fence.cpp" + > + </File> + <File + RelativePath=".\Framebuffer.cpp" + > + </File> + <File + RelativePath=".\HandleAllocator.cpp" + > + </File> + <File + RelativePath=".\IndexDataManager.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> + <File + RelativePath=".\VertexDataManager.cpp" + > + </File> + </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=".\Fence.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=".\HandleAllocator.h" + > + </File> + <File + RelativePath=".\IndexDataManager.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=".\resource.h" + > + </File> + <File + RelativePath=".\ResourceManager.h" + > + </File> + <File + RelativePath=".\Shader.h" + > + </File> + <File + RelativePath=".\Texture.h" + > + </File> + <File + RelativePath=".\utilities.h" + > + </File> + <File + RelativePath="..\common\version.h" + > + </File> + <File + RelativePath=".\vertexconversion.h" + > + </File> + <File + RelativePath=".\VertexDataManager.h" + > + </File> + </Filter> + <File + RelativePath=".\libGLESv2.def" + > + </File> + <File + RelativePath=".\libGLESv2.rc" + > + </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 000000000..ad1156309 --- /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(); + TRACE("\t! Error generated: invalid enum\n"); + break; + case GL_INVALID_VALUE: + context->recordInvalidValue(); + TRACE("\t! Error generated: invalid value\n"); + break; + case GL_INVALID_OPERATION: + context->recordInvalidOperation(); + TRACE("\t! Error generated: invalid operation\n"); + break; + case GL_OUT_OF_MEMORY: + context->recordOutOfMemory(); + TRACE("\t! Error generated: out of memory\n"); + break; + case GL_INVALID_FRAMEBUFFER_OPERATION: + context->recordInvalidFramebufferOperation(); + TRACE("\t! Error generated: invalid framebuffer operation\n"); + break; + default: UNREACHABLE(); + } + } +} diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/main.h b/Source/ThirdParty/ANGLE/src/libGLESv2/main.h new file mode 100644 index 000000000..7f9c8807b --- /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 000000000..7ca2d9ffd --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/mathutil.h @@ -0,0 +1,119 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// mathutil.h: Math and bit manipulation functions. + +#ifndef LIBGLESV2_MATHUTIL_H_ +#define LIBGLESV2_MATHUTIL_H_ + +#include <intrin.h> +#include <math.h> +#include <windows.h> + +namespace gl +{ +inline bool isPow2(int x) +{ + return (x & (x - 1)) == 0 && (x != 0); +} + +inline int log2(int x) +{ + int r = 0; + while ((x >> r) > 1) r++; + return r; +} + +inline unsigned int ceilPow2(unsigned int x) +{ + if (x != 0) x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x++; + + return x; +} + +template<typename T, typename MIN, typename MAX> +inline T clamp(T x, MIN min, MAX max) +{ + return x < min ? min : (x > max ? max : x); +} + +inline float clamp01(float x) +{ + return clamp(x, 0.0f, 1.0f); +} + +template<const int n> +inline unsigned int unorm(float x) +{ + const unsigned int max = 0xFFFFFFFF >> (32 - n); + + if (x > 1) + { + return max; + } + else if (x < 0) + { + return 0; + } + else + { + return (unsigned int)(max * x + 0.5f); + } +} + +inline RECT transformPixelRect(GLint x, GLint y, GLint w, GLint h, GLint surfaceHeight) +{ + RECT rect = {x, + surfaceHeight - y - h, + x + w, + surfaceHeight - y}; + return rect; +} + +inline int transformPixelYOffset(GLint yoffset, GLint h, GLint surfaceHeight) +{ + return surfaceHeight - yoffset - h; +} + +inline GLenum adjustWinding(GLenum winding) +{ + ASSERT(winding == GL_CW || winding == GL_CCW); + return winding == GL_CW ? GL_CCW : GL_CW; +} + +inline bool supportsSSE2() +{ + static bool checked = false; + static bool supports = false; + + if (checked) + { + return supports; + } + + int info[4]; + __cpuid(info, 0); + + if (info[0] >= 1) + { + __cpuid(info, 1); + + supports = (info[3] >> 26) & 1; + } + + checked = true; + + return supports; +} +} + +#endif // LIBGLESV2_MATHUTIL_H_ diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/resource.h b/Source/ThirdParty/ANGLE/src/libGLESv2/resource.h new file mode 100644 index 000000000..39adaad0d --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by libGLESv2.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.cpp new file mode 100644 index 000000000..ba23fd365 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.cpp @@ -0,0 +1,882 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// utilities.cpp: Conversion functions and other utility routines. + +#include "libGLESv2/utilities.h" + +#include <limits> +#include <stdio.h> +#include <windows.h> + +#include "common/debug.h" + +#include "libGLESv2/mathutil.h" +#include "libGLESv2/Context.h" + +namespace gl +{ + +int UniformComponentCount(GLenum type) +{ + switch (type) + { + case GL_BOOL: + case GL_FLOAT: + case GL_INT: + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: + return 1; + case GL_BOOL_VEC2: + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + return 2; + case GL_INT_VEC3: + case GL_FLOAT_VEC3: + case GL_BOOL_VEC3: + return 3; + case GL_BOOL_VEC4: + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_FLOAT_MAT2: + return 4; + case GL_FLOAT_MAT3: + return 9; + case GL_FLOAT_MAT4: + return 16; + default: + UNREACHABLE(); + } + + return 0; +} + +GLenum UniformComponentType(GLenum type) +{ + switch(type) + { + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + return GL_BOOL; + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: + return GL_FLOAT; + case GL_INT: + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: + return GL_INT; + default: + UNREACHABLE(); + } + + return GL_NONE; +} + +size_t UniformTypeSize(GLenum type) +{ + switch(type) + { + case GL_BOOL: return sizeof(GLboolean); + case GL_FLOAT: return sizeof(GLfloat); + case GL_INT: return sizeof(GLint); + } + + return UniformTypeSize(UniformComponentType(type)) * UniformComponentCount(type); +} + +int VariableRowCount(GLenum type) +{ + switch (type) + { + case GL_NONE: + return 0; + case GL_BOOL: + case GL_FLOAT: + case GL_INT: + case GL_BOOL_VEC2: + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_FLOAT_VEC3: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + return 1; + case GL_FLOAT_MAT2: + return 2; + case GL_FLOAT_MAT3: + return 3; + case GL_FLOAT_MAT4: + return 4; + default: + UNREACHABLE(); + } + + return 0; +} + +int VariableColumnCount(GLenum type) +{ + switch (type) + { + case GL_NONE: + return 0; + case GL_BOOL: + case GL_FLOAT: + case GL_INT: + return 1; + case GL_BOOL_VEC2: + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_FLOAT_MAT2: + return 2; + case GL_INT_VEC3: + case GL_FLOAT_VEC3: + case GL_BOOL_VEC3: + case GL_FLOAT_MAT3: + return 3; + case GL_BOOL_VEC4: + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_FLOAT_MAT4: + return 4; + default: + UNREACHABLE(); + } + + return 0; +} + +int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize) +{ + ASSERT(allocationSize <= bitsSize); + + unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize); + + for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++) + { + if ((*bits & mask) == 0) + { + *bits |= mask; + return i; + } + + mask <<= 1; + } + + return -1; +} + +GLsizei ComputePitch(GLsizei width, GLenum format, GLenum type, GLint alignment) +{ + ASSERT(alignment > 0 && isPow2(alignment)); + + GLsizei rawPitch = ComputePixelSize(format, type) * width; + return (rawPitch + alignment - 1) & ~(alignment - 1); +} + +GLsizei ComputeCompressedPitch(GLsizei width, GLenum format) +{ + return ComputeCompressedSize(width, 1, format); +} + +GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format) +{ + switch (format) + { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + 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); + case GL_FLOAT: + switch (format) + { + case GL_ALPHA: return sizeof(float); + case GL_LUMINANCE: return sizeof(float); + case GL_LUMINANCE_ALPHA: return sizeof(float) * 2; + case GL_RGB: return sizeof(float) * 3; + case GL_RGBA: return sizeof(float) * 4; + default: UNREACHABLE(); + } + break; + case GL_HALF_FLOAT_OES: + switch (format) + { + case GL_ALPHA: return sizeof(unsigned short); + case GL_LUMINANCE: return sizeof(unsigned short); + case GL_LUMINANCE_ALPHA: return sizeof(unsigned short) * 2; + case GL_RGB: return sizeof(unsigned short) * 3; + case GL_RGBA: return sizeof(unsigned short) * 4; + default: UNREACHABLE(); + } + break; + default: UNREACHABLE(); + } + + return 0; +} + +bool IsCubemapTextureTarget(GLenum target) +{ + return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); +} + +bool IsTextureTarget(GLenum target) +{ + return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target); +} + +// Verify that format/type are one of the combinations from table 3.4. +bool CheckTextureFormatType(GLenum format, GLenum type) +{ + switch (type) + { + case GL_UNSIGNED_BYTE: + switch (format) + { + case GL_RGBA: + case GL_BGRA_EXT: + case GL_RGB: + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + return true; + + default: + return false; + } + + case GL_FLOAT: + case GL_HALF_FLOAT_OES: + switch (format) + { + case GL_RGBA: + case GL_RGB: + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + return true; + + default: + return false; + } + + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + return (format == GL_RGBA); + + case GL_UNSIGNED_SHORT_5_6_5: + return (format == GL_RGB); + + default: + return false; + } +} + +bool IsColorRenderable(GLenum internalformat) +{ + switch (internalformat) + { + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGB565: + case GL_RGB8_OES: + case GL_RGBA8_OES: + return true; + case GL_DEPTH_COMPONENT16: + case GL_STENCIL_INDEX8: + case GL_DEPTH24_STENCIL8_OES: + return false; + default: + UNIMPLEMENTED(); + } + + return false; +} + +bool IsDepthRenderable(GLenum internalformat) +{ + switch (internalformat) + { + case GL_DEPTH_COMPONENT16: + case GL_DEPTH24_STENCIL8_OES: + return true; + case GL_STENCIL_INDEX8: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGB565: + case GL_RGB8_OES: + case GL_RGBA8_OES: + return false; + default: + UNIMPLEMENTED(); + } + + return false; +} + +bool IsStencilRenderable(GLenum internalformat) +{ + switch (internalformat) + { + case GL_STENCIL_INDEX8: + case GL_DEPTH24_STENCIL8_OES: + return true; + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGB565: + case GL_RGB8_OES: + case GL_RGBA8_OES: + case GL_DEPTH_COMPONENT16: + return false; + default: + UNIMPLEMENTED(); + } + + return false; +} + +} + +namespace es2dx +{ + +D3DCMPFUNC ConvertComparison(GLenum comparison) +{ + D3DCMPFUNC d3dComp = D3DCMP_ALWAYS; + switch (comparison) + { + case GL_NEVER: d3dComp = D3DCMP_NEVER; break; + case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break; + case GL_LESS: d3dComp = D3DCMP_LESS; break; + case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break; + case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break; + case GL_GREATER: d3dComp = D3DCMP_GREATER; break; + case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break; + case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break; + default: UNREACHABLE(); + } + + return d3dComp; +} + +D3DCOLOR ConvertColor(gl::Color color) +{ + return D3DCOLOR_RGBA(gl::unorm<8>(color.red), + gl::unorm<8>(color.green), + gl::unorm<8>(color.blue), + gl::unorm<8>(color.alpha)); +} + +D3DBLEND ConvertBlendFunc(GLenum blend) +{ + D3DBLEND d3dBlend = D3DBLEND_ZERO; + + switch (blend) + { + case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break; + case GL_ONE: d3dBlend = D3DBLEND_ONE; break; + case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break; + case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break; + case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break; + case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break; + case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break; + case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break; + case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break; + case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break; + case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; + case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break; + case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; + case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break; + default: UNREACHABLE(); + } + + return d3dBlend; +} + +D3DBLENDOP ConvertBlendOp(GLenum blendOp) +{ + D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD; + + switch (blendOp) + { + case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break; + case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break; + case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break; + default: UNREACHABLE(); + } + + return d3dBlendOp; +} + +D3DSTENCILOP ConvertStencilOp(GLenum stencilOp) +{ + D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP; + + switch (stencilOp) + { + case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break; + case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break; + case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break; + case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break; + case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break; + case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break; + case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break; + case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break; + default: UNREACHABLE(); + } + + return d3dStencilOp; +} + +D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap) +{ + D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP; + + switch (wrap) + { + case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break; + case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break; + case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break; + default: UNREACHABLE(); + } + + return d3dWrap; +} + +D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace) +{ + D3DCULL cull = D3DCULL_CCW; + switch (cullFace) + { + case GL_FRONT: + cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW); + break; + case GL_BACK: + cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW); + break; + case GL_FRONT_AND_BACK: + cull = D3DCULL_NONE; // culling will be handled during draw + break; + default: UNREACHABLE(); + } + + return cull; +} + +D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace) +{ + D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X; + + // Map a cube map texture target to the corresponding D3D surface index. Note that the + // Y faces are swapped because the Y coordinate to the texture lookup intrinsic functions + // are negated in the pixel shader. + switch (cubeFace) + { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + face = D3DCUBEMAP_FACE_POSITIVE_X; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + face = D3DCUBEMAP_FACE_NEGATIVE_X; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + face = D3DCUBEMAP_FACE_NEGATIVE_Y; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + face = D3DCUBEMAP_FACE_POSITIVE_Y; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + face = D3DCUBEMAP_FACE_POSITIVE_Z; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + face = D3DCUBEMAP_FACE_NEGATIVE_Z; + break; + default: UNREACHABLE(); + } + + return face; +} + +DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha) +{ + return (red ? D3DCOLORWRITEENABLE_RED : 0) | + (green ? D3DCOLORWRITEENABLE_GREEN : 0) | + (blue ? D3DCOLORWRITEENABLE_BLUE : 0) | + (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0); +} + +D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter) +{ + 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(); + } +} + +bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, + D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount) +{ + switch (primitiveType) + { + case GL_POINTS: + *d3dPrimitiveType = D3DPT_POINTLIST; + *d3dPrimitiveCount = elementCount; + break; + case GL_LINES: + *d3dPrimitiveType = D3DPT_LINELIST; + *d3dPrimitiveCount = elementCount / 2; + break; + case GL_LINE_LOOP: + *d3dPrimitiveType = D3DPT_LINESTRIP; + *d3dPrimitiveCount = elementCount - 1; // D3D doesn't support line loops, so we draw the last line separately + break; + case GL_LINE_STRIP: + *d3dPrimitiveType = D3DPT_LINESTRIP; + *d3dPrimitiveCount = elementCount - 1; + break; + case GL_TRIANGLES: + *d3dPrimitiveType = D3DPT_TRIANGLELIST; + *d3dPrimitiveCount = elementCount / 3; + break; + case GL_TRIANGLE_STRIP: + *d3dPrimitiveType = D3DPT_TRIANGLESTRIP; + *d3dPrimitiveCount = elementCount - 2; + break; + case GL_TRIANGLE_FAN: + *d3dPrimitiveType = D3DPT_TRIANGLEFAN; + *d3dPrimitiveCount = elementCount - 2; + break; + default: + return false; + } + + return true; +} + +D3DFORMAT ConvertRenderbufferFormat(GLenum format) +{ + switch (format) + { + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8_OES: return D3DFMT_A8R8G8B8; + case GL_RGB565: return D3DFMT_R5G6B5; + case GL_RGB8_OES: return D3DFMT_X8R8G8B8; + case GL_DEPTH_COMPONENT16: + case GL_STENCIL_INDEX8: + case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8; + default: UNREACHABLE(); return D3DFMT_A8R8G8B8; + } +} + +D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples) +{ + if (samples <= 1) + return D3DMULTISAMPLE_NONE; + else + return (D3DMULTISAMPLE_TYPE)samples; +} + +} + +namespace dx2es +{ + +unsigned int GetStencilSize(D3DFORMAT stencilFormat) +{ + switch(stencilFormat) + { + case D3DFMT_D24FS8: + case D3DFMT_D24S8: + return 8; + case D3DFMT_D24X4S4: + return 4; + case D3DFMT_D15S1: + return 1; + case D3DFMT_D16_LOCKABLE: + case D3DFMT_D32: + case D3DFMT_D24X8: + case D3DFMT_D32F_LOCKABLE: + case D3DFMT_D16: + return 0; + //case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only + //case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only + default: + return 0; + } +} + +unsigned int GetAlphaSize(D3DFORMAT colorFormat) +{ + switch (colorFormat) + { + case D3DFMT_A16B16G16R16F: + return 16; + case D3DFMT_A32B32G32R32F: + return 32; + case D3DFMT_A2R10G10B10: + return 2; + case D3DFMT_A8R8G8B8: + return 8; + case D3DFMT_A1R5G5B5: + return 1; + case D3DFMT_X8R8G8B8: + case D3DFMT_R5G6B5: + return 0; + default: + return 0; + } +} + +unsigned int GetRedSize(D3DFORMAT colorFormat) +{ + switch (colorFormat) + { + case D3DFMT_A16B16G16R16F: + return 16; + case D3DFMT_A32B32G32R32F: + return 32; + case D3DFMT_A2R10G10B10: + return 10; + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + return 8; + case D3DFMT_A1R5G5B5: + case D3DFMT_R5G6B5: + return 5; + default: + return 0; + } +} + +unsigned int GetGreenSize(D3DFORMAT colorFormat) +{ + switch (colorFormat) + { + case D3DFMT_A16B16G16R16F: + return 16; + case D3DFMT_A32B32G32R32F: + return 32; + case D3DFMT_A2R10G10B10: + return 10; + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + return 8; + case D3DFMT_A1R5G5B5: + return 5; + case D3DFMT_R5G6B5: + return 6; + default: + return 0; + } +} + +unsigned int GetBlueSize(D3DFORMAT colorFormat) +{ + switch (colorFormat) + { + case D3DFMT_A16B16G16R16F: + return 16; + case D3DFMT_A32B32G32R32F: + return 32; + case D3DFMT_A2R10G10B10: + return 10; + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + return 8; + case D3DFMT_A1R5G5B5: + case D3DFMT_R5G6B5: + return 5; + default: + return 0; + } +} + +unsigned int GetDepthSize(D3DFORMAT depthFormat) +{ + switch (depthFormat) + { + case D3DFMT_D16_LOCKABLE: return 16; + case D3DFMT_D32: return 32; + case D3DFMT_D15S1: return 15; + case D3DFMT_D24S8: return 24; + case D3DFMT_D24X8: return 24; + case D3DFMT_D24X4S4: return 24; + case D3DFMT_D16: return 16; + case D3DFMT_D32F_LOCKABLE: return 32; + case D3DFMT_D24FS8: return 24; + //case D3DFMT_D32_LOCKABLE: return 32; // D3D9Ex only + //case D3DFMT_S8_LOCKABLE: return 0; // D3D9Ex only + default: return 0; + } +} + +GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type) +{ + if (type == D3DMULTISAMPLE_NONMASKABLE) + return 0; + else + return type; +} + +GLenum ConvertBackBufferFormat(D3DFORMAT format) +{ + switch (format) + { + case D3DFMT_A4R4G4B4: return GL_RGBA4; + case D3DFMT_A8R8G8B8: return GL_RGBA8_OES; + case D3DFMT_A1R5G5B5: return GL_RGB5_A1; + case D3DFMT_R5G6B5: return GL_RGB565; + case D3DFMT_X8R8G8B8: return GL_RGB8_OES; + default: + UNREACHABLE(); + } + + return GL_RGBA4; +} + +GLenum ConvertDepthStencilFormat(D3DFORMAT format) +{ + switch (format) + { + case D3DFMT_D16: + case D3DFMT_D24X8: + return GL_DEPTH_COMPONENT16; + case D3DFMT_D24S8: + return GL_DEPTH24_STENCIL8_OES; + default: + UNREACHABLE(); + } + + return GL_DEPTH24_STENCIL8_OES; +} + +} + +std::string getTempPath() +{ + char path[MAX_PATH]; + DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path); + if (pathLen == 0) + { + UNREACHABLE(); + return std::string(); + } + + UINT unique = GetTempFileNameA(path, "sh", 0, path); + if (unique == 0) + { + UNREACHABLE(); + return std::string(); + } + + return path; +} + +void writeFile(const char* path, const void* content, size_t size) +{ + FILE* file = fopen(path, "w"); + if (!file) + { + UNREACHABLE(); + return; + } + + fwrite(content, sizeof(char), size, file); + fclose(file); +} diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.h b/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.h new file mode 100644 index 000000000..bf7f4f934 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.h @@ -0,0 +1,87 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// utilities.h: Conversion functions and other utility routines. + +#ifndef LIBGLESV2_UTILITIES_H +#define LIBGLESV2_UTILITIES_H + +#define GL_APICALL +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#include <d3d9.h> + +#include <string> + +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); + +bool IsColorRenderable(GLenum internalformat); +bool IsDepthRenderable(GLenum internalformat); +bool IsStencilRenderable(GLenum internalformat); + +} + +namespace es2dx +{ + +D3DCMPFUNC ConvertComparison(GLenum comparison); +D3DCOLOR ConvertColor(gl::Color color); +D3DBLEND ConvertBlendFunc(GLenum blend); +D3DBLENDOP ConvertBlendOp(GLenum blendOp); +D3DSTENCILOP ConvertStencilOp(GLenum stencilOp); +D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap); +D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace); +D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace); +DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha); +D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter); +void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter); +bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, + D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount); +D3DFORMAT ConvertRenderbufferFormat(GLenum format); +D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples); + +} + +namespace dx2es +{ +GLuint GetAlphaSize(D3DFORMAT colorFormat); +GLuint GetRedSize(D3DFORMAT colorFormat); +GLuint GetGreenSize(D3DFORMAT colorFormat); +GLuint GetBlueSize(D3DFORMAT colorFormat); +GLuint GetDepthSize(D3DFORMAT depthFormat); +GLuint GetStencilSize(D3DFORMAT stencilFormat); + +GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type); + +GLenum ConvertBackBufferFormat(D3DFORMAT format); +GLenum ConvertDepthStencilFormat(D3DFORMAT format); + +} + +std::string getTempPath(); +void writeFile(const char* path, const void* data, size_t size); + +#endif // LIBGLESV2_UTILITIES_H diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/vertexconversion.h b/Source/ThirdParty/ANGLE/src/libGLESv2/vertexconversion.h new file mode 100644 index 000000000..5bb8b8995 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/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. +// + +// vertexconversion.h: A library of vertex conversion classes that can be used to build +// the FormatConverter objects used by the buffer conversion system. + +#ifndef LIBGLESV2_VERTEXCONVERSION_H_ +#define LIBGLESV2_VERTEXCONVERSION_H_ + +#include <cstddef> +#include <limits> + +#include "libGLESv2/Context.h" // Defines Index + +namespace gl +{ + +// Conversion types: +// static const bool identity: true if this is an identity transform, false otherwise +// static U convert(T): convert a single element from the input type to the output type +// typedef ... OutputType: the type produced by this conversion + +template <class T> +struct Identity +{ + static const bool identity = true; + + typedef T OutputType; + + static T convert(T x) + { + return x; + } +}; + +template <class FromT, class ToT> +struct Cast +{ + static const bool identity = false; + + typedef ToT OutputType; + + static ToT convert(FromT x) + { + return static_cast<ToT>(x); + } +}; + +template <class T> +struct Cast<T, T> +{ + static const bool identity = true; + + typedef T OutputType; + + static T convert(T x) + { + return static_cast<T>(x); + } +}; + +template <class T> +struct Normalize +{ + static const bool identity = false; + + typedef float OutputType; + + static float convert(T x) + { + typedef std::numeric_limits<T> NL; + float f = static_cast<float>(x); + + if (NL::is_signed) + { + // const float => VC2008 computes it at compile time + // static const float => VC2008 computes it the first time we get here, stores it to memory with static guard and all that. + const float divisor = 1.0f/(2*static_cast<float>(NL::max())+1); + return (2*f+1)*divisor; + } + else + { + return f/NL::max(); + } + } +}; + +template <class FromType, std::size_t ScaleBits> +struct FixedToFloat +{ + static const bool identity = false; + + typedef float OutputType; + + static float convert(FromType x) + { + const float divisor = 1.0f / static_cast<float>(static_cast<FromType>(1) << ScaleBits); + return static_cast<float>(x) * divisor; + } +}; + +// Widen types: +// static const unsigned int initialWidth: number of components before conversion +// static const unsigned int finalWidth: number of components after conversion + +// Float is supported at any size. +template <std::size_t N> +struct NoWiden +{ + static const std::size_t initialWidth = N; + static const std::size_t finalWidth = N; +}; + +// SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components +template <std::size_t N> +struct WidenToEven +{ + static const std::size_t initialWidth = N; + static const std::size_t finalWidth = N+(N&1); +}; + +template <std::size_t N> +struct WidenToFour +{ + static const std::size_t initialWidth = N; + static const std::size_t finalWidth = 4; +}; + +// Most types have 0 and 1 that are just that. +template <class T> +struct SimpleDefaultValues +{ + static T zero() { return static_cast<T>(0); } + static T one() { return static_cast<T>(1); } +}; + +// But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value. +template <class T> +struct NormalizedDefaultValues +{ + static T zero() { return static_cast<T>(0); } + static T one() { return std::numeric_limits<T>::max(); } +}; + +// Converter: +// static const bool identity: true if this is an identity transform (with no widening) +// static const std::size_t finalSize: number of bytes per output vertex +// static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert an array of vertices. Input may be strided, but output will be unstrided. + +template <class InT, class WidenRule, class Converter, class DefaultValueRule = SimpleDefaultValues<InT> > +struct VertexDataConverter +{ + typedef typename Converter::OutputType OutputType; + typedef InT InputType; + + static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity; + static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType); + + static void convertArray(const InputType *in, std::size_t stride, std::size_t n, OutputType *out) + { + for (std::size_t i = 0; i < n; i++) + { + const InputType *ein = pointerAddBytes(in, i * stride); + + copyComponent(out, ein, 0, static_cast<OutputType>(DefaultValueRule::zero())); + copyComponent(out, ein, 1, static_cast<OutputType>(DefaultValueRule::zero())); + copyComponent(out, ein, 2, static_cast<OutputType>(DefaultValueRule::zero())); + copyComponent(out, ein, 3, static_cast<OutputType>(DefaultValueRule::one())); + + out += WidenRule::finalWidth; + } + } + + static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out) + { + return convertArray(static_cast<const InputType*>(in), stride, n, static_cast<OutputType*>(out)); + } + + private: + // Advance the given pointer by a number of bytes (not pointed-to elements). + template <class T> + static T *pointerAddBytes(T *basePtr, std::size_t numBytes) + { + return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(basePtr) + numBytes); + } + + static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue) + { + if (WidenRule::finalWidth > elementindex) + { + if (WidenRule::initialWidth > elementindex) + { + out[elementindex] = Converter::convert(in[elementindex]); + } + else + { + out[elementindex] = defaultvalue; + } + } + } +}; + +} + +#endif // LIBGLESV2_VERTEXCONVERSION_H_ |