From ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb Mon Sep 17 00:00:00 2001 From: Ben Murdoch Date: Mon, 16 May 2011 16:25:10 +0100 Subject: Merge WebKit at r76408: Initial merge by git. Change-Id: I5b91decbd693ccbf5c1b8354b37cd68cc9a1ea53 --- .../ANGLE/ANGLE.xcodeproj/project.pbxproj | 137 +- Source/ThirdParty/ANGLE/ChangeLog | 610 +++ .../ThirdParty/ANGLE/include/GLSLANG/ShaderLang.h | 228 +- .../src/build_angle.xcodeproj/project.pbxproj | 35 +- Source/ThirdParty/ANGLE/src/common/debug.cpp | 8 +- Source/ThirdParty/ANGLE/src/common/debug.h | 2 +- .../ThirdParty/ANGLE/src/compiler/CodeGenGLSL.cpp | 4 +- .../ThirdParty/ANGLE/src/compiler/CodeGenHLSL.cpp | 4 +- Source/ThirdParty/ANGLE/src/compiler/Common.h | 21 +- Source/ThirdParty/ANGLE/src/compiler/Compiler.cpp | 189 + .../ANGLE/src/compiler/ExtensionBehavior.h | 21 + Source/ThirdParty/ANGLE/src/compiler/InfoSink.cpp | 4 +- Source/ThirdParty/ANGLE/src/compiler/InfoSink.h | 1 + .../ThirdParty/ANGLE/src/compiler/Initialize.cpp | 122 +- Source/ThirdParty/ANGLE/src/compiler/Initialize.h | 10 +- .../ANGLE/src/compiler/IntermTraverse.cpp | 16 +- .../ThirdParty/ANGLE/src/compiler/Intermediate.cpp | 172 +- .../ThirdParty/ANGLE/src/compiler/OutputGLSL.cpp | 29 +- .../ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp | 86 +- Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.h | 2 +- .../ThirdParty/ANGLE/src/compiler/ParseHelper.cpp | 137 +- Source/ThirdParty/ANGLE/src/compiler/ParseHelper.h | 39 +- Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.cpp | 46 +- Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.h | 10 +- .../ThirdParty/ANGLE/src/compiler/SearchSymbol.cpp | 38 + .../ThirdParty/ANGLE/src/compiler/SearchSymbol.h | 33 + Source/ThirdParty/ANGLE/src/compiler/ShHandle.h | 64 +- .../ThirdParty/ANGLE/src/compiler/ShaderLang.cpp | 281 +- .../ThirdParty/ANGLE/src/compiler/SymbolTable.cpp | 16 + Source/ThirdParty/ANGLE/src/compiler/SymbolTable.h | 29 +- .../ANGLE/src/compiler/TranslatorGLSL.cpp | 29 +- .../ThirdParty/ANGLE/src/compiler/TranslatorGLSL.h | 6 +- .../ANGLE/src/compiler/TranslatorHLSL.cpp | 8 +- .../ThirdParty/ANGLE/src/compiler/TranslatorHLSL.h | 6 +- Source/ThirdParty/ANGLE/src/compiler/Types.h | 6 +- .../ThirdParty/ANGLE/src/compiler/UnfoldSelect.cpp | 4 +- .../ThirdParty/ANGLE/src/compiler/UnfoldSelect.h | 2 + .../ANGLE/src/compiler/ValidateLimitations.cpp | 468 ++ .../ANGLE/src/compiler/ValidateLimitations.h | 62 + .../ThirdParty/ANGLE/src/compiler/VariableInfo.cpp | 210 + .../ThirdParty/ANGLE/src/compiler/VariableInfo.h | 38 + .../ThirdParty/ANGLE/src/compiler/VersionGLSL.cpp | 108 + Source/ThirdParty/ANGLE/src/compiler/VersionGLSL.h | 50 + .../ANGLE/src/compiler/generate_glslang_lexer.sh | 11 + .../ANGLE/src/compiler/generate_glslang_parser.sh | 12 + Source/ThirdParty/ANGLE/src/compiler/glslang.h | 16 + Source/ThirdParty/ANGLE/src/compiler/glslang.l | 734 ++- Source/ThirdParty/ANGLE/src/compiler/glslang.y | 1108 +++-- .../ThirdParty/ANGLE/src/compiler/glslang_lex.cpp | 3186 +++++++++++++ .../ThirdParty/ANGLE/src/compiler/glslang_tab.cpp | 4710 ++++++++++++++++++++ Source/ThirdParty/ANGLE/src/compiler/glslang_tab.h | 274 ++ Source/ThirdParty/ANGLE/src/compiler/intermOut.cpp | 396 +- .../ThirdParty/ANGLE/src/compiler/intermediate.h | 54 +- .../ANGLE/src/compiler/localintermediate.h | 4 +- Source/ThirdParty/ANGLE/src/compiler/osinclude.h | 24 +- .../ANGLE/src/compiler/ossource_nspr.cpp | 43 + .../ANGLE/src/compiler/preprocessor/compile.h | 8 +- .../ANGLE/src/compiler/preprocessor/cpp.c | 59 +- .../ANGLE/src/compiler/preprocessor/preprocess.h | 4 +- .../ANGLE/src/compiler/preprocessor/scanner.c | 328 +- .../ANGLE/src/compiler/preprocessor/scanner.h | 9 +- .../ANGLE/src/compiler/preprocessor/tokens.c | 17 +- Source/ThirdParty/ANGLE/src/compiler/unistd.h | 1 - Source/ThirdParty/ANGLE/src/compiler/util.cpp | 33 + Source/ThirdParty/ANGLE/src/compiler/util.h | 21 + Source/ThirdParty/ANGLE/src/libEGL/Config.cpp | 7 - Source/ThirdParty/ANGLE/src/libEGL/Display.cpp | 301 +- Source/ThirdParty/ANGLE/src/libEGL/Display.h | 19 +- Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp | 266 +- Source/ThirdParty/ANGLE/src/libEGL/Surface.h | 19 +- Source/ThirdParty/ANGLE/src/libEGL/libEGL.cpp | 35 +- Source/ThirdParty/ANGLE/src/libGLESv2/Blit.cpp | 19 +- Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.cpp | 50 + Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.h | 9 + Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp | 633 ++- Source/ThirdParty/ANGLE/src/libGLESv2/Context.h | 135 +- Source/ThirdParty/ANGLE/src/libGLESv2/Fence.cpp | 134 + Source/ThirdParty/ANGLE/src/libGLESv2/Fence.h | 43 + .../ThirdParty/ANGLE/src/libGLESv2/Framebuffer.cpp | 54 +- Source/ThirdParty/ANGLE/src/libGLESv2/Program.cpp | 184 +- Source/ThirdParty/ANGLE/src/libGLESv2/Program.h | 10 +- .../ANGLE/src/libGLESv2/RefCountObject.cpp | 1 + .../ANGLE/src/libGLESv2/Renderbuffer.cpp | 48 +- .../ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.h | 5 +- Source/ThirdParty/ANGLE/src/libGLESv2/Shader.cpp | 35 +- Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp | 1054 ++++- Source/ThirdParty/ANGLE/src/libGLESv2/Texture.h | 74 +- .../src/libGLESv2/geometry/IndexDataManager.cpp | 383 +- .../src/libGLESv2/geometry/IndexDataManager.h | 107 +- .../src/libGLESv2/geometry/VertexDataManager.cpp | 766 +++- .../src/libGLESv2/geometry/VertexDataManager.h | 154 +- .../ANGLE/src/libGLESv2/geometry/backend.cpp | 38 - .../ANGLE/src/libGLESv2/geometry/backend.h | 110 - .../ANGLE/src/libGLESv2/geometry/dx9.cpp | 613 --- .../ThirdParty/ANGLE/src/libGLESv2/geometry/dx9.h | 137 - .../ThirdParty/ANGLE/src/libGLESv2/libGLESv2.cpp | 690 ++- .../ThirdParty/ANGLE/src/libGLESv2/libGLESv2.def | 9 +- .../ANGLE/src/libGLESv2/libGLESv2.vcproj | 24 +- .../ThirdParty/ANGLE/src/libGLESv2/utilities.cpp | 181 +- Source/ThirdParty/ANGLE/src/libGLESv2/utilities.h | 14 +- 100 files changed, 16498 insertions(+), 4306 deletions(-) create mode 100644 Source/ThirdParty/ANGLE/src/compiler/Compiler.cpp create mode 100644 Source/ThirdParty/ANGLE/src/compiler/ExtensionBehavior.h create mode 100644 Source/ThirdParty/ANGLE/src/compiler/SearchSymbol.cpp create mode 100644 Source/ThirdParty/ANGLE/src/compiler/SearchSymbol.h create mode 100644 Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.cpp create mode 100644 Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.h create mode 100644 Source/ThirdParty/ANGLE/src/compiler/VariableInfo.cpp create mode 100644 Source/ThirdParty/ANGLE/src/compiler/VariableInfo.h create mode 100644 Source/ThirdParty/ANGLE/src/compiler/VersionGLSL.cpp create mode 100644 Source/ThirdParty/ANGLE/src/compiler/VersionGLSL.h create mode 100644 Source/ThirdParty/ANGLE/src/compiler/generate_glslang_lexer.sh create mode 100644 Source/ThirdParty/ANGLE/src/compiler/generate_glslang_parser.sh create mode 100644 Source/ThirdParty/ANGLE/src/compiler/glslang.h create mode 100644 Source/ThirdParty/ANGLE/src/compiler/glslang_lex.cpp create mode 100644 Source/ThirdParty/ANGLE/src/compiler/glslang_tab.cpp create mode 100644 Source/ThirdParty/ANGLE/src/compiler/glslang_tab.h create mode 100644 Source/ThirdParty/ANGLE/src/compiler/ossource_nspr.cpp delete mode 100644 Source/ThirdParty/ANGLE/src/compiler/unistd.h create mode 100644 Source/ThirdParty/ANGLE/src/compiler/util.cpp create mode 100644 Source/ThirdParty/ANGLE/src/compiler/util.h create mode 100644 Source/ThirdParty/ANGLE/src/libGLESv2/Fence.cpp create mode 100644 Source/ThirdParty/ANGLE/src/libGLESv2/Fence.h delete mode 100644 Source/ThirdParty/ANGLE/src/libGLESv2/geometry/backend.cpp delete mode 100644 Source/ThirdParty/ANGLE/src/libGLESv2/geometry/backend.h delete mode 100644 Source/ThirdParty/ANGLE/src/libGLESv2/geometry/dx9.cpp delete mode 100644 Source/ThirdParty/ANGLE/src/libGLESv2/geometry/dx9.h (limited to 'Source/ThirdParty') diff --git a/Source/ThirdParty/ANGLE/ANGLE.xcodeproj/project.pbxproj b/Source/ThirdParty/ANGLE/ANGLE.xcodeproj/project.pbxproj index 066a930..aa91bdb 100644 --- a/Source/ThirdParty/ANGLE/ANGLE.xcodeproj/project.pbxproj +++ b/Source/ThirdParty/ANGLE/ANGLE.xcodeproj/project.pbxproj @@ -7,6 +7,22 @@ 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 */; }; 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 */; }; @@ -33,8 +49,6 @@ FB39D2AA1200F35A00088E69 /* SymbolTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D25C1200F35A00088E69 /* SymbolTable.cpp */; }; FB39D2AC1200F35A00088E69 /* TranslatorGLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D2681200F35A00088E69 /* TranslatorGLSL.cpp */; }; FB39D2B11200F35A00088E69 /* UnfoldSelect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D26D1200F35A00088E69 /* UnfoldSelect.cpp */; }; - FB39D7231201032000088E69 /* glslang.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D7201201032000088E69 /* glslang.cpp */; }; - FB39D7241201032000088E69 /* glslang_tab.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB39D7221201032000088E69 /* glslang_tab.cpp */; }; FB39D76E120110FC00088E69 /* ShaderLang.h in Headers */ = {isa = PBXBuildFile; fileRef = FB39D2BF1200F3E600088E69 /* ShaderLang.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ @@ -42,6 +56,23 @@ 5D7C59C51208C68B001C873E /* ANGLE.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ANGLE.xcconfig; sourceTree = ""; }; 5D7C59C61208C68B001C873E /* Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = ""; }; 5D7C59C71208C68B001C873E /* DebugRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugRelease.xcconfig; sourceTree = ""; }; + 90D9B0F912E11DCB002D4255 /* Compiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Compiler.cpp; sourceTree = ""; }; + 90D9B0FA12E11DCB002D4255 /* ExtensionBehavior.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExtensionBehavior.h; sourceTree = ""; }; + 90D9B0FB12E11DCB002D4255 /* glslang_lex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = glslang_lex.cpp; sourceTree = ""; }; + 90D9B0FC12E11DCB002D4255 /* glslang_tab.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = glslang_tab.cpp; sourceTree = ""; }; + 90D9B0FD12E11DCB002D4255 /* glslang_tab.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glslang_tab.h; sourceTree = ""; }; + 90D9B0FE12E11DCB002D4255 /* glslang.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glslang.h; sourceTree = ""; }; + 90D9B0FF12E11DCB002D4255 /* ossource_nspr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossource_nspr.cpp; sourceTree = ""; }; + 90D9B10012E11DCB002D4255 /* SearchSymbol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SearchSymbol.cpp; sourceTree = ""; }; + 90D9B10112E11DCB002D4255 /* SearchSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SearchSymbol.h; sourceTree = ""; }; + 90D9B10B12E11DD6002D4255 /* util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = util.cpp; sourceTree = ""; }; + 90D9B10C12E11DD6002D4255 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util.h; sourceTree = ""; }; + 90D9B10D12E11DD6002D4255 /* ValidateLimitations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ValidateLimitations.cpp; sourceTree = ""; }; + 90D9B10E12E11DD6002D4255 /* ValidateLimitations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValidateLimitations.h; sourceTree = ""; }; + 90D9B10F12E11DD6002D4255 /* VariableInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VariableInfo.cpp; sourceTree = ""; }; + 90D9B11012E11DD6002D4255 /* VariableInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VariableInfo.h; sourceTree = ""; }; + 90D9B11112E11DD6002D4255 /* VersionGLSL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VersionGLSL.cpp; sourceTree = ""; }; + 90D9B11212E11DD6002D4255 /* VersionGLSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VersionGLSL.h; sourceTree = ""; }; 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 = ""; }; FB39D1871200F26200088E69 /* CodeGenGLSL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = CodeGenGLSL.cpp; sourceTree = ""; }; @@ -50,8 +81,6 @@ FB39D18A1200F26200088E69 /* ConstantUnion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantUnion.h; sourceTree = ""; }; FB39D18B1200F26200088E69 /* debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = debug.cpp; sourceTree = ""; }; FB39D18C1200F26200088E69 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = ""; }; - FB39D18D1200F26200088E69 /* glslang.l */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.lex; path = glslang.l; sourceTree = ""; }; - FB39D18E1200F26200088E69 /* glslang.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; path = glslang.y; sourceTree = ""; }; FB39D18F1200F26200088E69 /* InfoSink.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = InfoSink.cpp; sourceTree = ""; }; FB39D1901200F26200088E69 /* InfoSink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InfoSink.h; sourceTree = ""; }; FB39D1911200F26200088E69 /* Initialize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = Initialize.cpp; sourceTree = ""; }; @@ -112,15 +141,12 @@ FB39D1D11200F26200088E69 /* Types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Types.h; sourceTree = ""; }; FB39D1D21200F26200088E69 /* UnfoldSelect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.cpp.cpp; path = UnfoldSelect.cpp; sourceTree = ""; }; FB39D1D31200F26200088E69 /* UnfoldSelect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnfoldSelect.h; sourceTree = ""; }; - FB39D1D41200F26200088E69 /* unistd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unistd.h; sourceTree = ""; }; FB39D2211200F35A00088E69 /* BaseTypes.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = BaseTypes.h; sourceTree = ""; }; FB39D2221200F35A00088E69 /* CodeGenGLSL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeGenGLSL.cpp; sourceTree = ""; }; FB39D2241200F35A00088E69 /* Common.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = Common.h; sourceTree = ""; }; FB39D2251200F35A00088E69 /* ConstantUnion.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = ConstantUnion.h; sourceTree = ""; }; FB39D2261200F35A00088E69 /* debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug.cpp; sourceTree = ""; }; FB39D2271200F35A00088E69 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = ""; }; - FB39D2281200F35A00088E69 /* glslang.l */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.lex; path = glslang.l; sourceTree = ""; }; - FB39D2291200F35A00088E69 /* glslang.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; path = glslang.y; sourceTree = ""; }; FB39D22A1200F35A00088E69 /* InfoSink.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InfoSink.cpp; sourceTree = ""; }; FB39D22B1200F35A00088E69 /* InfoSink.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = InfoSink.h; sourceTree = ""; }; FB39D22C1200F35A00088E69 /* Initialize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Initialize.cpp; sourceTree = ""; }; @@ -175,11 +201,7 @@ FB39D26C1200F35A00088E69 /* Types.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = Types.h; sourceTree = ""; }; FB39D26D1200F35A00088E69 /* UnfoldSelect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnfoldSelect.cpp; sourceTree = ""; }; FB39D26E1200F35A00088E69 /* UnfoldSelect.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = UnfoldSelect.h; sourceTree = ""; }; - FB39D26F1200F35A00088E69 /* unistd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unistd.h; sourceTree = ""; }; FB39D2BF1200F3E600088E69 /* ShaderLang.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = ShaderLang.h; sourceTree = ""; }; - FB39D7201201032000088E69 /* glslang.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = glslang.cpp; path = DerivedSources/ANGLE/glslang.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; - FB39D7211201032000088E69 /* glslang_tab.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = glslang_tab.h; path = DerivedSources/ANGLE/glslang_tab.h; sourceTree = BUILT_PRODUCTS_DIR; }; - FB39D7221201032000088E69 /* glslang_tab.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = glslang_tab.cpp; path = DerivedSources/ANGLE/glslang_tab.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -208,7 +230,6 @@ children = ( FB39D2201200F35A00088E69 /* compiler */, FB39D0841200EDEB00088E69 /* Source */, - FB39D0CB1200EF9400088E69 /* Intermediates */, 5D7C59C41208C68B001C873E /* Configurations */, FB39D0CC1200EF9B00088E69 /* Products */, ); @@ -223,16 +244,6 @@ name = Source; sourceTree = ""; }; - FB39D0CB1200EF9400088E69 /* Intermediates */ = { - isa = PBXGroup; - children = ( - FB39D7201201032000088E69 /* glslang.cpp */, - FB39D7211201032000088E69 /* glslang_tab.h */, - FB39D7221201032000088E69 /* glslang_tab.cpp */, - ); - name = Intermediates; - sourceTree = ""; - }; FB39D0CC1200EF9B00088E69 /* Products */ = { isa = PBXGroup; children = ( @@ -251,8 +262,6 @@ FB39D18A1200F26200088E69 /* ConstantUnion.h */, FB39D18B1200F26200088E69 /* debug.cpp */, FB39D18C1200F26200088E69 /* debug.h */, - FB39D18D1200F26200088E69 /* glslang.l */, - FB39D18E1200F26200088E69 /* glslang.y */, FB39D18F1200F26200088E69 /* InfoSink.cpp */, FB39D1901200F26200088E69 /* InfoSink.h */, FB39D1911200F26200088E69 /* Initialize.cpp */, @@ -297,7 +306,6 @@ FB39D1D11200F26200088E69 /* Types.h */, FB39D1D21200F26200088E69 /* UnfoldSelect.cpp */, FB39D1D31200F26200088E69 /* UnfoldSelect.h */, - FB39D1D41200F26200088E69 /* unistd.h */, ); includeInIndex = 0; name = compiler; @@ -332,14 +340,19 @@ FB39D2201200F35A00088E69 /* compiler */ = { isa = PBXGroup; children = ( + FB39D2441200F35A00088E69 /* preprocessor */, FB39D2211200F35A00088E69 /* BaseTypes.h */, FB39D2221200F35A00088E69 /* CodeGenGLSL.cpp */, FB39D2241200F35A00088E69 /* Common.h */, + 90D9B0F912E11DCB002D4255 /* Compiler.cpp */, FB39D2251200F35A00088E69 /* ConstantUnion.h */, FB39D2261200F35A00088E69 /* debug.cpp */, FB39D2271200F35A00088E69 /* debug.h */, - FB39D2281200F35A00088E69 /* glslang.l */, - FB39D2291200F35A00088E69 /* glslang.y */, + 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 */, @@ -355,6 +368,7 @@ FB39D2361200F35A00088E69 /* localintermediate.h */, FB39D2371200F35A00088E69 /* MMap.h */, FB39D2381200F35A00088E69 /* osinclude.h */, + 90D9B0FF12E11DCB002D4255 /* ossource_nspr.cpp */, FB39D2391200F35A00088E69 /* ossource_posix.cpp */, FB39D23A1200F35A00088E69 /* ossource_win.cpp */, FB39D23B1200F35A00088E69 /* OutputGLSL.cpp */, @@ -364,11 +378,12 @@ FB39D2411200F35A00088E69 /* ParseHelper.h */, FB39D2421200F35A00088E69 /* PoolAlloc.cpp */, FB39D2431200F35A00088E69 /* PoolAlloc.h */, - FB39D2441200F35A00088E69 /* preprocessor */, 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 */, @@ -378,7 +393,14 @@ FB39D26C1200F35A00088E69 /* Types.h */, FB39D26D1200F35A00088E69 /* UnfoldSelect.cpp */, FB39D26E1200F35A00088E69 /* UnfoldSelect.h */, - FB39D26F1200F35A00088E69 /* unistd.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; @@ -425,6 +447,14 @@ 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 */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -436,8 +466,6 @@ buildConfigurationList = FB39D0D61200F11E00088E69 /* Build configuration list for PBXNativeTarget "ANGLE" */; buildPhases = ( FB39D77B1201110C00088E69 /* Headers */, - FB39D0DE1200F19100088E69 /* Generate glslang lexer */, - FB39D31C1200F69200088E69 /* Generate glslang parser */, FB39D0CE1200F0E300088E69 /* Sources */, FB39D0CF1200F0E300088E69 /* Frameworks */, ); @@ -457,7 +485,6 @@ isa = PBXProject; buildConfigurationList = FB39D0731200ED9200088E69 /* Build configuration list for PBXProject "ANGLE" */; compatibilityVersion = "Xcode 2.4"; - developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( English, @@ -474,49 +501,11 @@ }; /* End PBXProject section */ -/* Begin PBXShellScriptBuildPhase section */ - FB39D0DE1200F19100088E69 /* Generate glslang lexer */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 12; - files = ( - ); - inputPaths = ( - "$(SRCROOT)/src/compiler/glslang.l", - ); - name = "Generate glslang lexer"; - outputPaths = ( - "$(BUILT_PRODUCTS_DIR)/DerivedSources/$(PROJECT_NAME)/glslang.cpp", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "mkdir -p \"${BUILT_PRODUCTS_DIR}/DerivedSources/${PROJECT_NAME}\"\nflex --noline --nounistd \"--outfile=${BUILT_PRODUCTS_DIR}/DerivedSources/${PROJECT_NAME}/glslang.cpp\" \"${SRCROOT}/src/compiler/glslang.l\"\n"; - }; - FB39D31C1200F69200088E69 /* Generate glslang parser */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "$(SRCROOT)/src/compiler/glslang.y", - ); - name = "Generate glslang parser"; - outputPaths = ( - "$(BUILT_PRODUCTS_DIR)/DerivedSources/$(PROJECT_NAME)/glslang_tab.cpp", - "$(BUILT_PRODUCTS_DIR)/DerivedSources/$(PROJECT_NAME)/glslang_tab.h", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "mkdir -p \"${BUILT_PRODUCTS_DIR}/DerivedSources/${PROJECT_NAME}\"\nbison --no-lines \"--defines=${BUILT_PRODUCTS_DIR}/DerivedSources/${PROJECT_NAME}/glslang_tab.h\" \"--skeleton=yacc.c\" \"--output=${BUILT_PRODUCTS_DIR}/DerivedSources/${PROJECT_NAME}/glslang_tab.cpp\" \"${SRCROOT}/src/compiler/glslang.y\"\n"; - }; -/* End PBXShellScriptBuildPhase section */ - /* Begin PBXSourcesBuildPhase section */ FB39D0CE1200F0E300088E69 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - FB39D7231201032000088E69 /* glslang.cpp in Sources */, - FB39D7241201032000088E69 /* glslang_tab.cpp in Sources */, FB39D2711200F35A00088E69 /* CodeGenGLSL.cpp in Sources */, FB39D2751200F35A00088E69 /* debug.cpp in Sources */, FB39D2791200F35A00088E69 /* InfoSink.cpp in Sources */, @@ -543,6 +532,14 @@ 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 */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Source/ThirdParty/ANGLE/ChangeLog b/Source/ThirdParty/ANGLE/ChangeLog index bd993b7..604df51 100644 --- a/Source/ThirdParty/ANGLE/ChangeLog +++ b/Source/ThirdParty/ANGLE/ChangeLog @@ -1,3 +1,613 @@ +2011-01-18 Kenneth Russell + + 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 + + Unreviewed, release build fix. Explicitly cast away const. + + * src/compiler/preprocessor/scanner.c: + (ScanFromString): + +2011-01-18 Ben Vanik + + 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 Rubber-stamped by Mark Rowe. diff --git a/Source/ThirdParty/ANGLE/include/GLSLANG/ShaderLang.h b/Source/ThirdParty/ANGLE/include/GLSLANG/ShaderLang.h index e0a5cc8..d0664e4 100644 --- a/Source/ThirdParty/ANGLE/include/GLSLANG/ShaderLang.h +++ b/Source/ThirdParty/ANGLE/include/GLSLANG/ShaderLang.h @@ -14,6 +14,66 @@ #ifdef __cplusplus extern "C" { #endif + +// Version number for shader translation API. +// It is incremented everytime the API changes. +#define SH_VERSION 103 + +// +// 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_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 +} 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 +} ShCompileOptions; + // // Driver must call this first, once, before doing any other // compiler operations. @@ -25,23 +85,6 @@ int ShInitialize(); // If the function succeeds, the return value is nonzero, else zero. // int ShFinalize(); -// -// Types of languages the compiler can consume. -// -typedef enum { - EShLangVertex, - EShLangFragment, - EShLangCount, -} EShLanguage; - -// -// The language specification compiler conforms to. -// It currently supports OpenGL ES and WebGL specifications. -// -typedef enum { - EShSpecGLES2, - EShSpecWebGL, -} EShSpec; // // Implementation dependent built-in resources (constants and extensions). @@ -62,27 +105,12 @@ typedef struct // Extensions. // Set to 1 to enable the extension, else 0. int OES_standard_derivatives; -} TBuiltInResource; +} ShBuiltInResources; // // Initialize built-in resources with minimum expected values. // -void ShInitBuiltInResource(TBuiltInResource* resources); - -// -// Optimization level for the compiler. -// -typedef enum { - EShOptNoGeneration, - EShOptNone, - EShOptSimple, // Optimizations that can be done quickly - EShOptFull, // Optimizations that will take more time -} EShOptimizationLevel; - -enum TDebugOptions { - EDebugOpNone = 0x000, - EDebugOpIntermediate = 0x001, // Writes intermediate tree into info-log. -}; +void ShInitBuiltInResources(ShBuiltInResources* resources); // // ShHandle held by but opaque to the driver. It is allocated, @@ -96,30 +124,130 @@ typedef void* ShHandle; // // Driver calls these to create and destroy compiler objects. // -ShHandle ShConstructCompiler(EShLanguage, EShSpec, const TBuiltInResource*); -void ShDestruct(ShHandle); +// Returns the handle of constructed compiler. +// 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. +// resources: Specifies the built-in resources. +ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, + const ShBuiltInResources* resources); +void ShDestruct(ShHandle handle); // -// The return value of ShCompile is boolean, indicating -// success or failure. -// -// The info-log should be written by ShCompile into -// ShHandle, so it can answer future queries. +// 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, + const ShHandle handle, const char* const shaderStrings[], const int numStrings, - const EShOptimizationLevel, - int debugOptions + int compileOptions ); -// -// All the following return 0 if the information is not -// available in the object passed down, or the object is bad. -// -const char* ShGetInfoLog(const ShHandle); -const char* ShGetObjectCode(const ShHandle); +// 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. +// +// 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. +void ShGetActiveAttrib(const ShHandle handle, + int index, + int* length, + int* size, + ShDataType* type, + char* name); + +// 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. +void ShGetActiveUniform(const ShHandle handle, + int index, + int* length, + int* size, + ShDataType* type, + char* name); #ifdef __cplusplus } diff --git a/Source/ThirdParty/ANGLE/src/build_angle.xcodeproj/project.pbxproj b/Source/ThirdParty/ANGLE/src/build_angle.xcodeproj/project.pbxproj index f118435..67f7e29 100644 --- a/Source/ThirdParty/ANGLE/src/build_angle.xcodeproj/project.pbxproj +++ b/Source/ThirdParty/ANGLE/src/build_angle.xcodeproj/project.pbxproj @@ -35,7 +35,6 @@ /* Begin PBXBuildFile section */ 05563ADFEA15116D7233332F /* QualifierAlive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4857E18799D332C30EF460C7 /* QualifierAlive.cpp */; }; 0A216949103E1E228F9C12F0 /* InitializeDll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 60C3998C9CE66DE0C5B0FD99 /* InitializeDll.cpp */; }; - 0D4064167398A6892809A09E /* glslang_tab.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A53D169CB849B861E15DF99A /* glslang_tab.cpp */; }; 3065D29E97FAC6E127388D15 /* Initialize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A54F2ED0D82D7BBCA4E9EEEA /* Initialize.cpp */; }; 32B1DBCD6B83F2146D787A62 /* atom.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C9B4616A65A5ABEF91FD6DC /* atom.c */; }; 35BE1BBEE6135A1CB0608EA8 /* cppstruct.c in Sources */ = {isa = PBXBuildFile; fileRef = 8058A0A2A0A02386867517EA /* cppstruct.c */; }; @@ -45,7 +44,6 @@ 6F9F875017A68ABE5D39FF19 /* ParseHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 976C831A75EBE009A9861796 /* ParseHelper.cpp */; }; 888F1382498E2D74AF2801C8 /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4ABA230FEA3654B030E4C4FB /* debug.cpp */; }; 9E8DFE1CCEF038BF2B65428C /* parseConst.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D2C9C8EB4A7EFF5B67FF9DBF /* parseConst.cpp */; }; - ABA5C61B1B78B9A8D69F6AEC /* glslang.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB1F91D3D8CC446F35B00D1B /* glslang.cpp */; }; AC23F58FDD3C55F5CA18EED7 /* RemoveTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B436EFF06913FCB19C3522A7 /* RemoveTree.cpp */; }; AD85517F086FDCEF3947C403 /* symbols.c in Sources */ = {isa = PBXBuildFile; fileRef = F013A7240BDAE8A61413D8C0 /* symbols.c */; }; B4858417E54365BE8CDE3919 /* ossource_posix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE258486005F6696CC031622 /* ossource_posix.cpp */; }; @@ -60,8 +58,6 @@ FB3C505711F7924A0081F5BA /* CodeGenGLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B7B1127C75B576FC00D74AED /* CodeGenGLSL.cpp */; }; FB3C505811F7924A0081F5BA /* OutputGLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 48B7402CC07A059FEF5EC351 /* OutputGLSL.cpp */; }; FB3C505911F7924A0081F5BA /* TranslatorGLSL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6FB70DC74A21FBCD665ABDF9 /* TranslatorGLSL.cpp */; }; - FB3C508E11F7949E0081F5BA /* glslang.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB1F91D3D8CC446F35B00D1B /* glslang.cpp */; }; - FB3C508F11F7949E0081F5BA /* glslang_tab.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A53D169CB849B861E15DF99A /* glslang_tab.cpp */; }; FB3C509211F794CE0081F5BA /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4ABA230FEA3654B030E4C4FB /* debug.cpp */; }; FB3C509311F794CE0081F5BA /* InfoSink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6E6927BE5D3C2C82F86111DF /* InfoSink.cpp */; }; FB3C509411F794CE0081F5BA /* Initialize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A54F2ED0D82D7BBCA4E9EEEA /* Initialize.cpp */; }; @@ -133,6 +129,10 @@ 5A21599C59BC1A75A7FABA34 /* OutputHLSL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OutputHLSL.h; sourceTree = ""; }; 60C3998C9CE66DE0C5B0FD99 /* InitializeDll.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InitializeDll.cpp; sourceTree = ""; }; 6BBC8224B9D8E234D117FA0C /* preprocess.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = preprocess.h; sourceTree = ""; }; + 6E02565112E6934D00B3431F /* glslang_lex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = glslang_lex.cpp; sourceTree = ""; }; + 6E02565212E6934D00B3431F /* glslang_tab.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = glslang_tab.cpp; sourceTree = ""; }; + 6E02565312E6934D00B3431F /* glslang_tab.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glslang_tab.h; sourceTree = ""; }; + 6E02565412E6934D00B3431F /* glslang.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glslang.h; sourceTree = ""; }; 6E6927BE5D3C2C82F86111DF /* InfoSink.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InfoSink.cpp; sourceTree = ""; }; 6FB70DC74A21FBCD665ABDF9 /* TranslatorGLSL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TranslatorGLSL.cpp; sourceTree = ""; }; 799DC9611EE2EA3BA7CF5477 /* intermediate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = intermediate.h; sourceTree = ""; }; @@ -143,7 +143,6 @@ 8513FAC699DB1558D1D49A48 /* Initialize.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Initialize.h; sourceTree = ""; }; 85845FFF5A8E63364308236D /* InitializeParseContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InitializeParseContext.h; sourceTree = ""; }; 89A6F7B1AD3918E64DF76EB1 /* slglobals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = slglobals.h; sourceTree = ""; }; - 8C3225C2F8C3573CD9725E66 /* glslang.y */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.yacc; path = glslang.y; sourceTree = ""; }; 93D61CB0BCE54E069D71F920 /* OutputGLSL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OutputGLSL.h; sourceTree = ""; }; 95276AA6B36FC1B1D913FCE4 /* debug.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = ""; }; 976C831A75EBE009A9861796 /* ParseHelper.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ParseHelper.cpp; sourceTree = ""; }; @@ -151,8 +150,6 @@ 9CED3AFF1E61B45EE1005656 /* atom.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = atom.h; sourceTree = ""; }; 9D47B1AC82E4EE859AC54243 /* QualifierAlive.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QualifierAlive.h; sourceTree = ""; }; A0CE43631849276A31187C7B /* InitializeDll.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InitializeDll.h; sourceTree = ""; }; - A3153D58F4BBBD98A84E4210 /* glslang.l */ = {isa = PBXFileReference; lastKnownFileType = text; path = glslang.l; sourceTree = ""; }; - A53D169CB849B861E15DF99A /* glslang_tab.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = glslang_tab.cpp; sourceTree = ""; }; A54F2ED0D82D7BBCA4E9EEEA /* Initialize.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Initialize.cpp; sourceTree = ""; }; AA53B6632C76F905DF08E564 /* Types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Types.h; sourceTree = ""; }; AE65E139AE10DE9EFAD8D5B1 /* ShHandle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ShHandle.h; sourceTree = ""; }; @@ -163,13 +160,11 @@ B75707B393B7EAB7DD9999CB /* cpp.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = cpp.c; sourceTree = ""; }; B7B1127C75B576FC00D74AED /* CodeGenGLSL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CodeGenGLSL.cpp; sourceTree = ""; }; B7E5B0F04635E6090F0DE8EF /* SymbolTable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolTable.cpp; sourceTree = ""; }; - BC66D6B47D9AF3286644BBE1 /* glslang_tab.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = glslang_tab.h; sourceTree = ""; }; BE258486005F6696CC031622 /* ossource_posix.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ossource_posix.cpp; sourceTree = ""; }; C3DAFF6BF12BB7F4784D6C7E /* TranslatorHLSL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TranslatorHLSL.cpp; sourceTree = ""; }; C49549DCCAF450EB761520E1 /* CodeGenHLSL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CodeGenHLSL.cpp; sourceTree = ""; }; C4FE988EF9A293867E5C771B /* IntermTraverse.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = IntermTraverse.cpp; sourceTree = ""; }; C8BD59BD7056FFC21373C50A /* osinclude.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = osinclude.h; sourceTree = ""; }; - CB1F91D3D8CC446F35B00D1B /* glslang.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = glslang.cpp; sourceTree = ""; }; CEE0C90DF6D504D1F3629711 /* ParseHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ParseHelper.h; sourceTree = ""; }; CF2B62E0820C831AF812D000 /* build_angle.gyp */ = {isa = PBXFileReference; lastKnownFileType = text; path = build_angle.gyp; sourceTree = ""; }; CFD12C6E46EBE0839BBE52B5 /* parser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = parser.h; sourceTree = ""; }; @@ -233,6 +228,10 @@ 196DB6AB006BB83503C7D786 /* Source */ = { isa = PBXGroup; children = ( + 6E02565112E6934D00B3431F /* glslang_lex.cpp */, + 6E02565212E6934D00B3431F /* glslang_tab.cpp */, + 6E02565312E6934D00B3431F /* glslang_tab.h */, + 6E02565412E6934D00B3431F /* glslang.h */, 0E8D65F584FDB84DAABD3969 /* preprocessor */, 27E4C7ED0B82E18DCBEDF1C9 /* BaseTypes.h */, B7B1127C75B576FC00D74AED /* CodeGenGLSL.cpp */, @@ -275,8 +274,6 @@ 2A765B86CBAF0D4A3E69DCA7 /* UnfoldSelect.h */, 4ABA230FEA3654B030E4C4FB /* debug.cpp */, 95276AA6B36FC1B1D913FCE4 /* debug.h */, - A3153D58F4BBBD98A84E4210 /* glslang.l */, - 8C3225C2F8C3573CD9725E66 /* glslang.y */, DEAF6F3126C2EC4397785C3F /* intermOut.cpp */, 799DC9611EE2EA3BA7CF5477 /* intermediate.h */, 153BF06BF12C6F50496C6156 /* localintermediate.h */, @@ -289,21 +286,10 @@ path = compiler; sourceTree = ""; }; - 466E1D0531A79B5813E8A7F8 /* Intermediates */ = { - isa = PBXGroup; - children = ( - CB1F91D3D8CC446F35B00D1B /* glslang.cpp */, - A53D169CB849B861E15DF99A /* glslang_tab.cpp */, - BC66D6B47D9AF3286644BBE1 /* glslang_tab.h */, - ); - name = Intermediates; - sourceTree = INTERMEDIATE_DIR; - }; 5BBEFF9B91738297B95C568D = { isa = PBXGroup; children = ( 196DB6AB006BB83503C7D786 /* Source */, - 466E1D0531A79B5813E8A7F8 /* Intermediates */, E0EDC4130E7D374318CE72BE /* Products */, B2C184C3543198BA51592EA4 /* Build */, ); @@ -373,7 +359,6 @@ }; buildConfigurationList = 0E59F8FE4A8099E8DDCA4CE7 /* Build configuration list for PBXProject "build_angle" */; compatibilityVersion = "Xcode 3.1"; - developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( English, @@ -457,8 +442,6 @@ F098F463EDABCF0769007678 /* scanner.c in Sources */, AD85517F086FDCEF3947C403 /* symbols.c in Sources */, E8C727AA8E9DC5E7B58857DF /* tokens.c in Sources */, - ABA5C61B1B78B9A8D69F6AEC /* glslang.cpp in Sources */, - 0D4064167398A6892809A09E /* glslang_tab.cpp in Sources */, B4858417E54365BE8CDE3919 /* ossource_posix.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -476,7 +459,6 @@ FB3C50A811F794FF0081F5BA /* scanner.c in Sources */, FB3C50A911F794FF0081F5BA /* symbols.c in Sources */, FB3C50AA11F794FF0081F5BA /* tokens.c in Sources */, - FB3C508E11F7949E0081F5BA /* glslang.cpp in Sources */, FB3C505711F7924A0081F5BA /* CodeGenGLSL.cpp in Sources */, FB3C509211F794CE0081F5BA /* debug.cpp in Sources */, FB3C509311F794CE0081F5BA /* InfoSink.cpp in Sources */, @@ -495,7 +477,6 @@ FB3C50A011F794CE0081F5BA /* ShaderLang.cpp in Sources */, FB3C50A111F794CE0081F5BA /* SymbolTable.cpp in Sources */, FB3C505911F7924A0081F5BA /* TranslatorGLSL.cpp in Sources */, - FB3C508F11F7949E0081F5BA /* glslang_tab.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Source/ThirdParty/ANGLE/src/common/debug.cpp b/Source/ThirdParty/ANGLE/src/common/debug.cpp index d8d6ab8..3de5d4e 100644 --- a/Source/ThirdParty/ANGLE/src/common/debug.cpp +++ b/Source/ThirdParty/ANGLE/src/common/debug.cpp @@ -11,17 +11,22 @@ #include #include +#ifndef TRACE_OUTPUT_FILE +#define TRACE_OUTPUT_FILE "debug.txt" +#endif + static bool trace_on = true; namespace gl { void trace(const char *format, ...) { +#if !defined(ANGLE_DISABLE_TRACE) if (trace_on) { if (format) { - FILE *file = fopen("debug.txt", "a"); + FILE *file = fopen(TRACE_OUTPUT_FILE, "a"); if (file) { @@ -34,5 +39,6 @@ void trace(const char *format, ...) } } } +#endif // !defined(ANGLE_DISABLE_TRACE) } } diff --git a/Source/ThirdParty/ANGLE/src/common/debug.h b/Source/ThirdParty/ANGLE/src/common/debug.h index 9a5135b..2c4ec70 100644 --- a/Source/ThirdParty/ANGLE/src/common/debug.h +++ b/Source/ThirdParty/ANGLE/src/common/debug.h @@ -19,7 +19,7 @@ namespace gl } // A macro to output a trace of a function call and its arguments to the debugging log -#ifndef NDEBUG +#if !defined(NDEBUG) && !defined(ANGLE_DISABLE_TRACE) #define TRACE(message, ...) gl::trace("trace: %s"message"\n", __FUNCTION__, __VA_ARGS__) #else #define TRACE(...) ((void)0) diff --git a/Source/ThirdParty/ANGLE/src/compiler/CodeGenGLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/CodeGenGLSL.cpp index 855b092..d140b37 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/CodeGenGLSL.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/CodeGenGLSL.cpp @@ -11,9 +11,9 @@ // compile object used by higher level code. It returns // a subclass of TCompiler. // -TCompiler* ConstructCompiler(EShLanguage language, EShSpec spec) +TCompiler* ConstructCompiler(ShShaderType type, ShShaderSpec spec) { - return new TranslatorGLSL(language, spec); + return new TranslatorGLSL(type, spec); } // diff --git a/Source/ThirdParty/ANGLE/src/compiler/CodeGenHLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/CodeGenHLSL.cpp index 4db771d..e04e789 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/CodeGenHLSL.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/CodeGenHLSL.cpp @@ -11,9 +11,9 @@ // compile object used by higher level code. It returns // a subclass of TCompiler. // -TCompiler* ConstructCompiler(EShLanguage language, EShSpec spec) +TCompiler* ConstructCompiler(ShShaderType type, ShShaderSpec spec) { - return new TranslatorHLSL(language, spec); + return new TranslatorHLSL(type, spec); } // diff --git a/Source/ThirdParty/ANGLE/src/compiler/Common.h b/Source/ThirdParty/ANGLE/src/compiler/Common.h index 65d0a51..27a5598 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/Common.h +++ b/Source/ThirdParty/ANGLE/src/compiler/Common.h @@ -14,9 +14,24 @@ #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 SourceLocLineMask = 0xffff; -const unsigned int SourceLocStringShift = 16; +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. @@ -71,6 +86,4 @@ public: TMap(const tAllocator& a) : std::map(std::map::key_compare(), a) {} }; -typedef TMap TPragmaTable; - #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 0000000..649b457 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/Compiler.cpp @@ -0,0 +1,189 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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" + +namespace { +bool InitializeSymbolTable( + const TBuiltInStrings& builtInStrings, + ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources, + TInfoSink& infoSink, TSymbolTable& symbolTable) +{ + TIntermediate intermediate(infoSink); + TExtensionBehavior extBehavior; + TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, 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(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; + + TIntermediate intermediate(infoSink); + TParseContext parseContext(symbolTable, extensionBehavior, intermediate, + shaderType, shaderSpec, 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, shaderStrings, 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); + + if (success && (compileOptions & SH_INTERMEDIATE_TREE)) + intermediate.outputTree(root); + + if (success && (compileOptions & SH_OBJECT_CODE)) + translate(root); + + if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) + collectAttribsUniforms(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); +} diff --git a/Source/ThirdParty/ANGLE/src/compiler/ExtensionBehavior.h b/Source/ThirdParty/ANGLE/src/compiler/ExtensionBehavior.h new file mode 100644 index 0000000..da96c24 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/ExtensionBehavior.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 _EXTENSION_BEHAVIOR_INCLUDED_ +#define _EXTENSION_BEHAVIOR_INCLUDED_ + +#include "compiler/Common.h" + +typedef enum { + EBhRequire, + EBhEnable, + EBhWarn, + EBhDisable +} TBehavior; + +typedef TMap TExtensionBehavior; + +#endif // _EXTENSION_TABLE_INCLUDED_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/InfoSink.cpp b/Source/ThirdParty/ANGLE/src/compiler/InfoSink.cpp index 317a88f..ba32f78 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/InfoSink.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/InfoSink.cpp @@ -32,8 +32,8 @@ void TInfoSinkBase::prefix(TPrefixType message) { } void TInfoSinkBase::location(TSourceLoc loc) { - int string = loc >> SourceLocStringShift; - int line = loc & SourceLocLineMask; + int string = 0, line = 0; + DecodeSourceLoc(loc, &string, &line); TPersistStringStream stream; if (line) diff --git a/Source/ThirdParty/ANGLE/src/compiler/InfoSink.h b/Source/ThirdParty/ANGLE/src/compiler/InfoSink.h index 4762778..e2224e9 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/InfoSink.h +++ b/Source/ThirdParty/ANGLE/src/compiler/InfoSink.h @@ -91,6 +91,7 @@ public: } void erase() { sink.clear(); } + int size() { return static_cast(sink.size()); } const TPersistString& str() const { return sink; } const char* c_str() const { return sink.c_str(); } diff --git a/Source/ThirdParty/ANGLE/src/compiler/Initialize.cpp b/Source/ThirdParty/ANGLE/src/compiler/Initialize.cpp index 6bfcf4f..12b53fe 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/Initialize.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/Initialize.cpp @@ -311,15 +311,6 @@ static TString BuiltInFunctionsCommon() s.append(TString("bvec4 not(bvec4 x);")); // - // Texture Functions. - // - s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord);")); - s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord);")); - s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord);")); - - s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord);")); - - // // Noise functions. // //s.append(TString("float noise1(float x);")); @@ -342,7 +333,6 @@ static TString BuiltInFunctionsCommon() //s.append(TString("vec4 noise4(vec3 x);")); //s.append(TString("vec4 noise4(vec4 x);")); - s.append(TString("\n")); return s; } @@ -351,7 +341,7 @@ static TString BuiltInFunctionsCommon() // Prototypes for built-in functions seen by vertex shaders only. // //============================================================================ -static TString BuiltInFunctionsVertex() +static TString BuiltInFunctionsVertex(const ShBuiltInResources& resources) { TString s; @@ -363,12 +353,18 @@ static TString BuiltInFunctionsVertex() // // Texture Functions. // - s.append(TString("vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);")); - s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);")); - s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);")); - s.append(TString("vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);")); + if (resources.MaxVertexTextureImageUnits > 0) { + 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);")); + } - s.append(TString("\n")); return s; } @@ -377,34 +373,40 @@ static TString BuiltInFunctionsVertex() // Prototypes for built-in functions seen by fragment shaders only. // //============================================================================ -static TString BuiltInFunctionsFragment() +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);")); - //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);")); + 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);")); + } - s.append(TString("\n")); return s; } @@ -427,7 +429,6 @@ static TString StandardUniforms() s.append(TString("};")); s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;")); - s.append(TString("\n")); return s; } @@ -443,7 +444,6 @@ static TString DefaultPrecisionVertex() s.append(TString("precision highp int;")); s.append(TString("precision highp float;")); - s.append(TString("\n")); return s; } @@ -459,7 +459,6 @@ static TString DefaultPrecisionFragment() s.append(TString("precision mediump int;")); // No default precision for float in fragment shaders - s.append(TString("\n")); return s; } @@ -468,7 +467,7 @@ static TString DefaultPrecisionFragment() // Implementation dependent built-in constants. // //============================================================================ -static TString BuiltInConstants(const TBuiltInResource &resources) +static TString BuiltInConstants(const ShBuiltInResources &resources) { TStringStream s; @@ -485,20 +484,21 @@ static TString BuiltInConstants(const TBuiltInResource &resources) return s.str(); } -void TBuiltIns::initialize(EShLanguage language, EShSpec spec, const TBuiltInResource& resources) +void TBuiltIns::initialize(ShShaderType type, ShShaderSpec spec, + const ShBuiltInResources& resources) { - switch (language) { - case EShLangFragment: + switch (type) { + case SH_FRAGMENT_SHADER: builtInStrings.push_back(DefaultPrecisionFragment()); builtInStrings.push_back(BuiltInFunctionsCommon()); - builtInStrings.push_back(BuiltInFunctionsFragment()); + builtInStrings.push_back(BuiltInFunctionsFragment(resources)); builtInStrings.push_back(StandardUniforms()); break; - case EShLangVertex: + case SH_VERTEX_SHADER: builtInStrings.push_back(DefaultPrecisionVertex()); builtInStrings.push_back(BuiltInFunctionsCommon()); - builtInStrings.push_back(BuiltInFunctionsVertex()); + builtInStrings.push_back(BuiltInFunctionsVertex(resources)); builtInStrings.push_back(StandardUniforms()); break; @@ -508,14 +508,16 @@ void TBuiltIns::initialize(EShLanguage language, EShSpec spec, const TBuiltInRes builtInStrings.push_back(BuiltInConstants(resources)); } -void IdentifyBuiltIns(EShLanguage language, EShSpec spec, const TBuiltInResource& resources, TSymbolTable& symbolTable) +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(language) { - case EShLangFragment: + 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))); @@ -523,7 +525,7 @@ void IdentifyBuiltIns(EShLanguage language, EShSpec spec, const TBuiltInResource symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2))); break; - case EShLangVertex: + 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; @@ -591,20 +593,26 @@ void IdentifyBuiltIns(EShLanguage language, EShSpec spec, const TBuiltInResource symbolTable.relateToOperator("all", EOpAll); // Map language-specific operators. - switch(language) { - case EShLangVertex: + switch(type) { + case SH_VERTEX_SHADER: break; - case EShLangFragment: - //symbolTable.relateToOperator("dFdx", EOpDPdx); // OES_standard_derivatives extension - //symbolTable.relateToOperator("dFdy", EOpDPdy); // OES_standard_derivatives extension - //symbolTable.relateToOperator("fwidth", EOpFwidth); // OES_standard_derivatives extension + 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(language) { - case EShLangFragment: { + 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); @@ -615,3 +623,9 @@ void IdentifyBuiltIns(EShLanguage language, EShSpec spec, const TBuiltInResource } } +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 index c078659..8b0adc6 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/Initialize.h +++ b/Source/ThirdParty/ANGLE/src/compiler/Initialize.h @@ -17,17 +17,19 @@ class TBuiltIns { public: POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - void initialize(EShLanguage language, EShSpec spec, const TBuiltInResource& resources); + void initialize(ShShaderType type, ShShaderSpec spec, + const ShBuiltInResources& resources); const TBuiltInStrings& getBuiltInStrings() { return builtInStrings; } protected: TBuiltInStrings builtInStrings; }; -void IdentifyBuiltIns(EShLanguage language, EShSpec spec, const TBuiltInResource& resources, +void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, + const ShBuiltInResources& resources, TSymbolTable& symbolTable); -extern "C" int InitPreprocessor(void); -extern "C" int FinalizePreprocessor(void); +void InitExtensionBehavior(const ShBuiltInResources& resources, + TExtensionBehavior& extensionBehavior); #endif // _INITIALIZE_INCLUDED_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/IntermTraverse.cpp b/Source/ThirdParty/ANGLE/src/compiler/IntermTraverse.cpp index 34a6f3c..a13877f 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/IntermTraverse.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/IntermTraverse.cpp @@ -229,9 +229,9 @@ void TIntermLoop::traverse(TIntermTraverser* it) if(it->rightToLeft) { - if(terminal) + if(expr) { - terminal->traverse(it); + expr->traverse(it); } if(body) @@ -239,16 +239,16 @@ void TIntermLoop::traverse(TIntermTraverser* it) body->traverse(it); } - if(test) + if(cond) { - test->traverse(it); + cond->traverse(it); } } else { - if(test) + if(cond) { - test->traverse(it); + cond->traverse(it); } if(body) @@ -256,9 +256,9 @@ void TIntermLoop::traverse(TIntermTraverser* it) body->traverse(it); } - if(terminal) + if(expr) { - terminal->traverse(it); + expr->traverse(it); } } diff --git a/Source/ThirdParty/ANGLE/src/compiler/Intermediate.cpp b/Source/ThirdParty/ANGLE/src/compiler/Intermediate.cpp index 5ebd919..ea71234 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/Intermediate.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/Intermediate.cpp @@ -22,6 +22,101 @@ 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. @@ -51,18 +146,23 @@ TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType 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->getType().isMatrix() || left->getType().isArray() || left->getType().isVector() || left->getType().getBasicType() == EbtStruct) { + if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) { return 0; } break; case EOpLogicalOr: case EOpLogicalXor: case EOpLogicalAnd: - if (left->getType().getBasicType() != EbtBool || left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector()) { + if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) { return 0; } break; @@ -70,7 +170,7 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn case EOpSub: case EOpDiv: case EOpMul: - if (left->getType().getBasicType() == EbtStruct || left->getType().getBasicType() == EbtBool) + if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) return 0; default: break; } @@ -78,8 +178,10 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn // // First try converting the children to compatible types. // - - if (!(left->getType().getStruct() && right->getType().getStruct())) { + 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; @@ -90,12 +192,8 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn else return 0; } - } else { - if (left->getType() != right->getType()) - return 0; } - // // Need a new node holding things together then. Make // one and promote it to the right type. @@ -107,18 +205,16 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn node->setLeft(left); node->setRight(right); - if (! node->promote(infoSink)) + if (!node->promote(infoSink)) return 0; - TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion(); - TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion(); - // // See if we can fold constants. // - TIntermTyped* typedReturnNode = 0; - if ( leftTempConstant && rightTempConstant) { + TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion(); + TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion(); + if (leftTempConstant && rightTempConstant) { typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink); if (typedReturnNode) @@ -602,9 +698,9 @@ TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line) // // Create loop nodes. // -TIntermNode* TIntermediate::addLoop(TIntermNode *init, TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, TSourceLoc line) +TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, TSourceLoc line) { - TIntermNode* node = new TIntermLoop(init, body, test, terminal, testFirst); + TIntermNode* node = new TIntermLoop(type, init, cond, expr, body); node->setLine(line); return node; @@ -630,7 +726,7 @@ TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expres // This is to be executed once the final root is put on top by the parsing // process. // -bool TIntermediate::postProcess(TIntermNode* root, EShLanguage language) +bool TIntermediate::postProcess(TIntermNode* root) { if (root == 0) return true; @@ -760,6 +856,12 @@ bool TIntermUnary::promote(TInfoSink&) // 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()) @@ -781,40 +883,6 @@ bool TIntermBinary::promote(TInfoSink& infoSink) getTypePointer()->setQualifier(EvqTemporary); } - // - // Array operations. - // - if (left->isArray() || right->isArray()) { - // - // Arrays types have to be exact matches. - // - if (left->getType() != right->getType()) - return false; - - switch (op) { - // - // Promote to conditional - // - case EOpEqual: - case EOpNotEqual: - setType(TType(EbtBool, EbpUndefined)); - break; - - // - // Set array information. - // - case EOpAssign: - case EOpInitialize: - getTypePointer()->setArraySize(left->getType().getArraySize()); - getTypePointer()->setArrayInformationType(left->getType().getArrayInformationType()); - break; - - default: - return false; - } - return true; - } - int size = std::max(left->getNominalSize(), right->getNominalSize()); // diff --git a/Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.cpp index fd263b6..23476f2 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/OutputGLSL.cpp @@ -374,6 +374,10 @@ bool TOutputGLSL::visitUnary(Visit visit, TIntermUnary* node) 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; @@ -608,23 +612,32 @@ bool TOutputGLSL::visitLoop(Visit visit, TIntermLoop* node) incrementDepth(); // Loop header. - if (node->testFirst()) // for loop + TLoopType loopType = node->getType(); + if (loopType == ELoopFor) // for loop { out << "for ("; if (node->getInit()) node->getInit()->traverse(this); out << "; "; - ASSERT(node->getTest() != NULL); - node->getTest()->traverse(this); + if (node->getCondition()) + node->getCondition()->traverse(this); out << "; "; - if (node->getTerminal()) - node->getTerminal()->traverse(this); + 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"; } @@ -632,11 +645,11 @@ bool TOutputGLSL::visitLoop(Visit visit, TIntermLoop* node) visitCodeBlock(node->getBody()); // Loop footer. - if (!node->testFirst()) // while loop + if (loopType == ELoopDoWhile) // do-while loop { out << "while ("; - ASSERT(node->getTest() != NULL); - node->getTest()->traverse(this); + ASSERT(node->getCondition() != NULL); + node->getCondition()->traverse(this); out << ");\n"; } decrementDepth(); diff --git a/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp index 8b8a4e6..57e99d2 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp @@ -9,6 +9,7 @@ #include "compiler/debug.h" #include "compiler/InfoSink.h" #include "compiler/UnfoldSelect.h" +#include "compiler/SearchSymbol.h" #include #include @@ -64,7 +65,7 @@ OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, tr mScopeDepth = 0; - mArgumentIndex = 0; + mUniqueIndex = 0; } OutputHLSL::~OutputHLSL() @@ -96,7 +97,7 @@ int OutputHLSL::vectorSize(const TType &type) const void OutputHLSL::header() { - EShLanguage language = mContext.language; + ShShaderType shaderType = mContext.shaderType; TInfoSinkBase &out = mHeader; for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++) @@ -109,7 +110,7 @@ void OutputHLSL::header() out << *constructor; } - if (language == EShLangFragment) + if (shaderType == SH_FRAGMENT_SHADER) { TString uniforms; TString varyings; @@ -361,7 +362,8 @@ void OutputHLSL::header() " float diff;\n" "};\n" "\n" - "uniform gl_DepthRangeParameters gl_DepthRange;\n" + "uniform float3 dx_DepthRange;" + "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" "\n"; } @@ -653,7 +655,39 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) switch (node->getOp()) { case EOpAssign: outputTriplet(visit, "(", " = ", ")"); break; - case EOpInitialize: 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; @@ -933,9 +967,9 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) case EOpFract: outputTriplet(visit, "frac(", "", ")"); break; case EOpLength: outputTriplet(visit, "length(", "", ")"); break; case EOpNormalize: outputTriplet(visit, "normalize(", "", ")"); break; -// case EOpDPdx: outputTriplet(visit, "ddx(", "", ")"); break; -// case EOpDPdy: outputTriplet(visit, "ddy(", "", ")"); break; -// case EOpFwidth: outputTriplet(visit, "fwidth(", "", ")"); break; + case 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(); @@ -946,7 +980,7 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { - EShLanguage language = mContext.language; + ShShaderType shaderType = mContext.shaderType; TInfoSinkBase &out = mBody; switch (node->getOp()) @@ -1392,7 +1426,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) TInfoSinkBase &out = mBody; - if (!node->testFirst()) + if (node->getType() == ELoopDoWhile) { out << "do\n" "{\n"; @@ -1404,14 +1438,14 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) mUnfoldSelect->traverse(node->getInit()); } - if (node->getTest()) + if (node->getCondition()) { - mUnfoldSelect->traverse(node->getTest()); + mUnfoldSelect->traverse(node->getCondition()); } - if (node->getTerminal()) + if (node->getExpression()) { - mUnfoldSelect->traverse(node->getTerminal()); + mUnfoldSelect->traverse(node->getExpression()); } out << "for("; @@ -1423,16 +1457,16 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) out << "; "; - if (node->getTest()) + if (node->getCondition()) { - node->getTest()->traverse(this); + node->getCondition()->traverse(this); } out << "; "; - if (node->getTerminal()) + if (node->getExpression()) { - node->getTerminal()->traverse(this); + node->getExpression()->traverse(this); } out << ")\n" @@ -1446,11 +1480,11 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) out << "}\n"; - if (!node->testFirst()) + if (node->getType() == ELoopDoWhile) { out << "while(\n"; - node->getTest()->traverse(this); + node->getCondition()->traverse(this); out << ")"; } @@ -1565,9 +1599,9 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) } // Parse comparator and limit value - if (index != NULL && node->getTest()) + if (index != NULL && node->getCondition()) { - TIntermBinary *test = node->getTest()->getAsBinaryNode(); + TIntermBinary *test = node->getCondition()->getAsBinaryNode(); if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId()) { @@ -1585,10 +1619,10 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) } // Parse increment - if (index != NULL && comparator != EOpNull && node->getTerminal()) + if (index != NULL && comparator != EOpNull && node->getExpression()) { - TIntermBinary *binaryTerminal = node->getTerminal()->getAsBinaryNode(); - TIntermUnary *unaryTerminal = node->getTerminal()->getAsUnaryNode(); + TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode(); + TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode(); if (binaryTerminal) { @@ -1711,7 +1745,7 @@ TString OutputHLSL::argumentString(const TIntermSymbol *symbol) if (name.empty()) // HLSL demands named arguments, also for prototypes { - name = "x" + str(mArgumentIndex++); + name = "x" + str(mUniqueIndex++); } else { diff --git a/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.h b/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.h index dc3c482..ddbd077 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.h +++ b/Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.h @@ -120,7 +120,7 @@ class OutputHLSL : public TIntermTraverser ScopeBracket mScopeBracket; unsigned int mScopeDepth; - int mArgumentIndex; // For creating unique argument names + int mUniqueIndex; // For creating unique names }; } diff --git a/Source/ThirdParty/ANGLE/src/compiler/ParseHelper.cpp b/Source/ThirdParty/ANGLE/src/compiler/ParseHelper.cpp index 407226b..53f3fa8 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/ParseHelper.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/ParseHelper.cpp @@ -9,9 +9,35 @@ #include #include +#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 @@ -176,24 +202,32 @@ void TParseContext::recover() // // Used by flex/bison to output all syntax and parsing errors. // -void TParseContext::error(TSourceLoc nLine, const char *szReason, const char *szToken, - const char *szExtraInfoFormat, ...) +void TParseContext::error(TSourceLoc loc, + const char* reason, const char* token, + const char* extraInfoFormat, ...) { - char szExtraInfo[400]; + char extraInfo[512]; va_list marker; + va_start(marker, extraInfoFormat); + vsnprintf(extraInfo, sizeof(extraInfo), extraInfoFormat, marker); - va_start(marker, szExtraInfoFormat); + ReportInfo(infoSink.info, EPrefixError, loc, reason, token, extraInfo); - vsnprintf(szExtraInfo, sizeof(szExtraInfo), szExtraInfoFormat, marker); + va_end(marker); + ++numErrors; +} - /* VC++ format: file(linenum) : error #: 'token' : extrainfo */ - infoSink.info.prefix(EPrefixError); - infoSink.info.location(nLine); - infoSink.info << "'" << szToken << "' : " << szReason << " " << szExtraInfo << "\n"; +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); - va_end(marker); + ReportInfo(infoSink.info, EPrefixWarning, loc, reason, token, extraInfo); - ++numErrors; + va_end(marker); } // @@ -415,7 +449,7 @@ bool TParseContext::reservedErrorCheck(int line, const TString& identifier) error(line, reservedErrMsg, "gl_", ""); return true; } - if (spec == EShSpecWebGL) { + if (shaderSpec == SH_WEBGL_SPEC) { if (identifier.substr(0, 6) == TString("webgl_")) { error(line, reservedErrMsg, "webgl_", ""); return true; @@ -471,17 +505,18 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction bool matrixInMatrix = false; bool arrayArg = false; for (int i = 0; i < function.getParamCount(); ++i) { - size += function[i].type->getObjectSize(); + const TParameter& param = function.getParam(i); + size += param.type->getObjectSize(); - if (constructingMatrix && function[i].type->isMatrix()) + if (constructingMatrix && param.type->isMatrix()) matrixInMatrix = true; if (full) overFull = true; if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize()) full = true; - if (function[i].type->getQualifier() != EvqConst) + if (param.type->getQualifier() != EvqConst) constType = false; - if (function[i].type->isArray()) + if (param.type->isArray()) arrayArg = true; } @@ -510,7 +545,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction return true; } - if (op == EOpConstructStruct && !type->isArray() && type->getStruct()->size() != function.getParamCount()) { + 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; } @@ -674,14 +709,11 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size) // bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type) { - if (type.qualifier == EvqAttribute) { + if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) { error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str(), ""); return true; } - if (type.qualifier == EvqConst && extensionErrorCheck(line, "GL_3DL_array_objects")) - return true; - return false; } @@ -886,16 +918,22 @@ bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier p return false; } -bool TParseContext::extensionErrorCheck(int line, const char* extension) -{ - if (extensionBehavior[extension] == EBhWarn) { - infoSink.info.message(EPrefixWarning, ("extension " + TString(extension) + " is being used").c_str(), line); - return false; +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 (extensionBehavior[extension] == EBhDisable) { - error(line, "extension", extension, "is disabled"); + 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; } @@ -1021,6 +1059,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) { + ASSERT(aggrNode != NULL); if (!aggrNode->isConstructor()) return false; @@ -1028,13 +1067,10 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) // check if all the child nodes are constants so that they can be inserted into // the parent node - if (aggrNode) { - TIntermSequence &childSequenceVector = aggrNode->getSequence() ; - for (TIntermSequence::iterator p = childSequenceVector.begin(); - p != childSequenceVector.end(); p++) { - if (!(*p)->getAsTyped()->getAsConstantUnion()) - return false; - } + TIntermSequence &sequence = aggrNode->getSequence() ; + for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) { + if (!(*p)->getAsTyped()->getAsConstantUnion()) + return false; } return allConstant; @@ -1379,16 +1415,29 @@ TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* n } // -// Initialize all supported extensions to disable +// Parse an array of strings using yyparse. // -void TParseContext::initializeExtensionBehavior() -{ - // - // example code: extensionBehavior["test"] = EBhDisable; // where "test" is the name of - // supported extension - // - extensionBehavior["GL_ARB_texture_rectangle"] = EBhRequire; - extensionBehavior["GL_3DL_array_objects"] = EBhDisable; +// 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; diff --git a/Source/ThirdParty/ANGLE/src/compiler/ParseHelper.h b/Source/ThirdParty/ANGLE/src/compiler/ParseHelper.h index 792333f..cb6e0d0 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/ParseHelper.h +++ b/Source/ThirdParty/ANGLE/src/compiler/ParseHelper.h @@ -6,9 +6,10 @@ #ifndef _PARSER_HELPER_INCLUDED_ #define _PARSER_HELPER_INCLUDED_ +#include "compiler/ExtensionBehavior.h" +#include "compiler/localintermediate.h" #include "compiler/ShHandle.h" #include "compiler/SymbolTable.h" -#include "compiler/localintermediate.h" struct TMatrixFields { bool wholeRow; @@ -17,13 +18,6 @@ struct TMatrixFields { int col; }; -typedef enum { - EBhRequire, - EBhEnable, - EBhWarn, - EBhDisable -} TBehavior; - struct TPragma { TPragma(bool o, bool d) : optimize(o), debug(d) { } bool optimize; @@ -36,15 +30,16 @@ struct TPragma { // they can be passed to the parser without needing a global. // struct TParseContext { - TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage l, EShSpec s, TInfoSink& is) : - intermediate(interm), symbolTable(symt), infoSink(is), language(l), spec(s), treeRoot(0), + TParseContext(TSymbolTable& symt, const TExtensionBehavior& ext, TIntermediate& interm, ShShaderType type, ShShaderSpec spec, TInfoSink& is) : + intermediate(interm), symbolTable(symt), extensionBehavior(ext), infoSink(is), shaderType(type), shaderSpec(spec), treeRoot(0), recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0), - inTypeParen(false), contextPragma(true, false) { } + 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; - EShLanguage language; // vertex or fragment language (future: pack or unpack) - EShSpec spec; // The language specification compiler conforms to - GLES2 or WebGL. + ShShaderType shaderType; // vertex or fragment language (future: pack or unpack) + ShShaderSpec shaderSpec; // The language specification compiler conforms to - GLES2 or WebGL. TIntermNode* treeRoot; // root of parse tree being created bool recoveredFromError; // true if a parse error has occurred, but we continue to parse int numErrors; @@ -53,11 +48,11 @@ struct TParseContext { bool inTypeParen; // true if in parentheses, looking only for an identifier const TType* currentFunctionType; // the return type of the function that's currently being parsed bool functionReturnsValue; // true if a non-void function has a return - TMap extensionBehavior; - void initializeExtensionBehavior(); - void error(TSourceLoc, const char *szReason, const char *szToken, - const char *szExtraInfoFormat, ...); + 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(); @@ -86,7 +81,7 @@ struct TParseContext { bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type); bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type); bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type); - bool extensionErrorCheck(int line, const char*); + 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); @@ -100,16 +95,14 @@ struct TParseContext { 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(char* argv[], int strLen[], int argc, TParseContext&); -void PaReservedWord(); -int PaIdentOrType(TString& id, TParseContext&, TSymbol*&); -int PaParseComment(int &lineno, TParseContext&); -void setInitialState(); +int PaParseStrings(int count, const char* const string[], const int length[], + TParseContext* context); typedef TParseContext* TParseContextPointer; extern TParseContextPointer& GetGlobalParseContext(); diff --git a/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.cpp b/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.cpp index 7e348ca..93e21e4 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.cpp @@ -22,14 +22,10 @@ void InitializeGlobalPools() if (globalPools) return; - TPoolAllocator *globalPoolAllocator = new TPoolAllocator(true); - TThreadGlobalPools* threadData = new TThreadGlobalPools(); - - threadData->globalPoolAllocator = globalPoolAllocator; - - OS_SetTLSValue(PoolIndex, threadData); - globalPoolAllocator->push(); + threadData->globalPoolAllocator = 0; + + OS_SetTLSValue(PoolIndex, threadData); } void FreeGlobalPools() @@ -38,9 +34,7 @@ void FreeGlobalPools() TThreadGlobalPools* globalPools= static_cast(OS_GetTLSValue(PoolIndex)); if (!globalPools) return; - - GlobalPoolAllocator.popAll(); - delete &GlobalPoolAllocator; + delete globalPools; } @@ -66,7 +60,7 @@ TPoolAllocator& GetGlobalPoolAllocator() return *threadData->globalPoolAllocator; } -void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator) +void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator) { TThreadGlobalPools* threadData = static_cast(OS_GetTLSValue(PoolIndex)); @@ -77,13 +71,13 @@ void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator) // Implement the functionality of the TPoolAllocator class, which // is documented in PoolAlloc.h. // -TPoolAllocator::TPoolAllocator(bool g, int growthIncrement, int allocationAlignment) : - global(g), +TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) : pageSize(growthIncrement), alignment(allocationAlignment), freeList(0), inUseList(0), - numCalls(0) + numCalls(0), + totalBytes(0) { // // Don't allow page sizes we know are smaller than all common @@ -123,24 +117,14 @@ TPoolAllocator::TPoolAllocator(bool g, int growthIncrement, int allocationAlignm TPoolAllocator::~TPoolAllocator() { - if (!global) { - // - // Then we know that this object is not being - // allocated after other, globally scoped objects - // that depend on it. So we can delete the "in use" memory. - // - while (inUseList) { - tHeader* next = inUseList->nextPage; - inUseList->~tHeader(); - delete [] reinterpret_cast(inUseList); - inUseList = next; - } + while (inUseList) { + tHeader* next = inUseList->nextPage; + inUseList->~tHeader(); + delete [] reinterpret_cast(inUseList); + inUseList = next; } - // - // Always delete the free list memory - it can't be being - // (correctly) referenced, whether the pool allocator was - // global or not. We should not check the guard blocks + // We should not check the guard blocks // here, because we did it already when the block was // placed into the free list. // @@ -315,4 +299,4 @@ void TAllocation::checkAllocList() const { for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc) alloc->check(); -} +} \ No newline at end of file diff --git a/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.h b/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.h index 645db78..051dc00 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.h +++ b/Source/ThirdParty/ANGLE/src/compiler/PoolAlloc.h @@ -115,7 +115,7 @@ private: // class TPoolAllocator { public: - TPoolAllocator(bool global = false, int growthIncrement = 8*1024, int allocationAlignment = 16); + TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16); // // Don't call the destructor just to free up the memory, call pop() @@ -194,7 +194,6 @@ protected: return TAllocation::offsetAllocation(memory); } - bool global; // should be true if this object is globally scoped size_t pageSize; // granularity of allocation from the OS size_t alignment; // all returned allocations will be aligned at // this granularity, which will be a power of 2 @@ -220,18 +219,15 @@ private: // different times. But a simple use is to have a global pop // with everyone using the same global allocator. // -typedef TPoolAllocator* PoolAllocatorPointer; extern TPoolAllocator& GetGlobalPoolAllocator(); +extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator); #define GlobalPoolAllocator GetGlobalPoolAllocator() - struct TThreadGlobalPools { TPoolAllocator* globalPoolAllocator; }; -void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator); - // // This STL compatible allocator is intended to be used as the allocator // parameter to templatized STL containers, like vector and map. @@ -301,4 +297,4 @@ protected: TPoolAllocator& allocator; }; -#endif // _POOLALLOC_INCLUDED_ +#endif // _POOLALLOC_INCLUDED_ \ No newline at end of file diff --git a/Source/ThirdParty/ANGLE/src/compiler/SearchSymbol.cpp b/Source/ThirdParty/ANGLE/src/compiler/SearchSymbol.cpp new file mode 100644 index 0000000..9368f1a --- /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 0000000..6bc0b90 --- /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 index 5ef5d30..e65c1ee 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/ShHandle.h +++ b/Source/ThirdParty/ANGLE/src/compiler/ShHandle.h @@ -16,20 +16,26 @@ #include "GLSLANG/ShaderLang.h" +#include "compiler/ExtensionBehavior.h" #include "compiler/InfoSink.h" #include "compiler/SymbolTable.h" +#include "compiler/VariableInfo.h" class TCompiler; -class TIntermNode; // // The base class used to back handles returned to the driver. // class TShHandleBase { public: - TShHandleBase() { } - virtual ~TShHandleBase() { } + 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; }; // @@ -38,27 +44,49 @@ public: // class TCompiler : public TShHandleBase { public: - TCompiler(EShLanguage l, EShSpec s) : language(l), spec(s) { } - virtual ~TCompiler() { } - - EShLanguage getLanguage() const { return language; } - EShSpec getSpec() const { return spec; } - TSymbolTable& getSymbolTable() { return symbolTable; } - TInfoSink& getInfoSink() { return infoSink; } + TCompiler(ShShaderType type, ShShaderSpec spec); + virtual ~TCompiler(); + virtual TCompiler* getAsCompiler() { return this; } - virtual bool compile(TIntermNode* root) = 0; + bool Init(const ShBuiltInResources& resources); + bool compile(const char* const shaderStrings[], + const int numStrings, + int compileOptions); - virtual TCompiler* getAsCompiler() { return this; } + // Get results of the last compilation. + TInfoSink& getInfoSink() { return infoSink; } + const TVariableInfoList& getAttribs() const { return attribs; } + const TVariableInfoList& getUniforms() const { return uniforms; } protected: - EShLanguage language; - EShSpec spec; + 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); + // Translate to object code. + virtual void translate(TIntermNode* root) = 0; + +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; - // Output sink. - TInfoSink infoSink; + // 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. }; // @@ -70,7 +98,7 @@ protected: // destroy the machine dependent objects, which contain the // above machine independent information. // -TCompiler* ConstructCompiler(EShLanguage, EShSpec); +TCompiler* ConstructCompiler(ShShaderType type, ShShaderSpec spec); void DeleteCompiler(TCompiler*); -#endif // _SHHANDLE_INCLUDED_ +#endif // _SHHANDLE_INCLUDED_ \ No newline at end of file diff --git a/Source/ThirdParty/ANGLE/src/compiler/ShaderLang.cpp b/Source/ThirdParty/ANGLE/src/compiler/ShaderLang.cpp index e0c646a..6cac61d 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/ShaderLang.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/ShaderLang.cpp @@ -11,78 +11,55 @@ #include "GLSLANG/ShaderLang.h" -#include "compiler/Initialize.h" #include "compiler/InitializeDll.h" -#include "compiler/ParseHelper.h" #include "compiler/ShHandle.h" -#include "compiler/SymbolTable.h" -static bool InitializeSymbolTable( - const TBuiltInStrings& builtInStrings, - EShLanguage language, EShSpec spec, const TBuiltInResource& resources, - TInfoSink& infoSink, TSymbolTable& symbolTable) -{ - TIntermediate intermediate(infoSink); - TParseContext parseContext(symbolTable, intermediate, language, spec, infoSink); - - GlobalParseContext = &parseContext; - - setInitialState(); - - assert(symbolTable.isEmpty()); - // - // Parse the built-ins. This should only happen once per - // language symbol table. - // - // Push the symbol table to give it an initial scope. This - // push should not have a corresponding pop, so that built-ins - // are preserved, and the test for an empty table fails. - // - symbolTable.push(); - - //Initialize the Preprocessor - if (InitPreprocessor()) - { - infoSink.info.message(EPrefixInternalError, "Unable to intialize the Preprocessor"); - return false; - } +// +// This is the platform independent interface between an OGL driver +// and the shading language compiler. +// - for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i) +static int getVariableMaxLength(const TVariableInfoList& varList) +{ + TString::size_type maxLen = 0; + for (TVariableInfoList::const_iterator i = varList.begin(); + i != varList.end(); ++i) { - const char* builtInShaders[1]; - int builtInLengths[1]; - - builtInShaders[0] = (*i).c_str(); - builtInLengths[0] = (int) (*i).size(); - - if (PaParseStrings(const_cast(builtInShaders), builtInLengths, 1, parseContext) != 0) - { - infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins"); - return false; - } + maxLen = std::max(maxLen, i->name.size()); } - - IdentifyBuiltIns(language, spec, resources, symbolTable); - - FinalizePreprocessor(); - - return true; + // Add 1 to include null-termination character. + return static_cast(maxLen) + 1; } -static bool GenerateBuiltInSymbolTable( - EShLanguage language, EShSpec spec, const TBuiltInResource& resources, - TInfoSink& infoSink, TSymbolTable& symbolTable) +static void getVariableInfo(ShShaderInfo varType, + const ShHandle handle, + int index, + int* length, + int* size, + ShDataType* type, + char* name) { - TBuiltIns builtIns; + if (!handle || !size || !type || !name) + return; + ASSERT((varType == SH_ACTIVE_ATTRIBUTES) || + (varType == SH_ACTIVE_UNIFORMS)); - builtIns.initialize(language, spec, resources); - return InitializeSymbolTable(builtIns.getBuiltInStrings(), language, spec, resources, infoSink, symbolTable); -} + TShHandleBase* base = reinterpret_cast(handle); + TCompiler* compiler = base->getAsCompiler(); + if (compiler == 0) + return; -// -// This is the platform independent interface between an OGL driver -// and the shading language compiler. -// + const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ? + compiler->getAttribs() : compiler->getUniforms(); + if (index < 0 || index >= static_cast(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()); +} // // Driver must call this first, once, before doing any other @@ -110,7 +87,7 @@ int ShFinalize() // // Initialize built-in resources with minimum expected values. // -void ShInitBuiltInResource(TBuiltInResource* resources) +void ShInitBuiltInResources(ShBuiltInResources* resources) { // Constants. resources->MaxVertexAttribs = 8; @@ -129,18 +106,19 @@ void ShInitBuiltInResource(TBuiltInResource* resources) // // Driver calls these to create and destroy compiler objects. // -ShHandle ShConstructCompiler(EShLanguage language, EShSpec spec, const TBuiltInResource* resources) +ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, + const ShBuiltInResources* resources) { if (!InitThread()) return 0; - TShHandleBase* base = static_cast(ConstructCompiler(language, spec)); + TShHandleBase* base = static_cast(ConstructCompiler(type, spec)); TCompiler* compiler = base->getAsCompiler(); if (compiler == 0) return 0; // Generate built-in symbol table. - if (!GenerateBuiltInSymbolTable(language, spec, *resources, compiler->getInfoSink(), compiler->getSymbolTable())) { + if (!compiler->Init(*resources)) { ShDestruct(base); return 0; } @@ -170,9 +148,7 @@ int ShCompile( const ShHandle handle, const char* const shaderStrings[], const int numStrings, - const EShOptimizationLevel optLevel, - int debugOptions - ) + int compileOptions) { if (!InitThread()) return 0; @@ -184,128 +160,95 @@ int ShCompile( TCompiler* compiler = base->getAsCompiler(); if (compiler == 0) return 0; - - GlobalPoolAllocator.push(); - TInfoSink& infoSink = compiler->getInfoSink(); - infoSink.info.erase(); - infoSink.debug.erase(); - infoSink.obj.erase(); - - if (numStrings == 0) - return 1; - - TIntermediate intermediate(infoSink); - TSymbolTable& symbolTable = compiler->getSymbolTable(); - - TParseContext parseContext(symbolTable, intermediate, compiler->getLanguage(), compiler->getSpec(), infoSink); - parseContext.initializeExtensionBehavior(); - GlobalParseContext = &parseContext; - - setInitialState(); - - InitPreprocessor(); - // - // Parse the application's shaders. All the following symbol table - // work will be throw-away, so push a new allocation scope that can - // be thrown away, then push a scope for the current shader's globals. - // - bool success = true; - - symbolTable.push(); - if (!symbolTable.atGlobalLevel()) - parseContext.infoSink.info.message(EPrefixInternalError, "Wrong symbol table level"); - - int ret = PaParseStrings(const_cast(shaderStrings), 0, numStrings, parseContext); - if (ret) - success = false; - - if (success && parseContext.treeRoot) { - if (optLevel == EShOptNoGeneration) - parseContext.infoSink.info.message(EPrefixNone, "No errors. No code generation was requested."); - else { - success = intermediate.postProcess(parseContext.treeRoot, parseContext.language); - - if (success) { - - if (debugOptions & EDebugOpIntermediate) - intermediate.outputTree(parseContext.treeRoot); - - // - // Call the machine dependent compiler - // - if (!compiler->compile(parseContext.treeRoot)) - success = false; - } - } - } else if (!success) { - parseContext.infoSink.info.prefix(EPrefixError); - parseContext.infoSink.info << parseContext.numErrors << " compilation errors. No code generated.\n\n"; - success = false; - if (debugOptions & EDebugOpIntermediate) - intermediate.outputTree(parseContext.treeRoot); - } else if (!parseContext.treeRoot) { - parseContext.error(1, "Unexpected end of file.", "", ""); - parseContext.infoSink.info << parseContext.numErrors << " compilation errors. No code generated.\n\n"; - success = false; - if (debugOptions & EDebugOpIntermediate) - intermediate.outputTree(parseContext.treeRoot); - } - intermediate.remove(parseContext.treeRoot); + bool success = compiler->compile(shaderStrings, numStrings, compileOptions); + return success ? 1 : 0; +} - // - // Ensure symbol table is returned to the built-in level, - // throwing away all but the built-ins. - // - while (!symbolTable.atBuiltInLevel()) - symbolTable.pop(); +void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params) +{ + if (!handle || !params) + return; - FinalizePreprocessor(); - // - // Throw away all the temporary memory used by the compilation process. - // - GlobalPoolAllocator.pop(); + TShHandleBase* base = static_cast(handle); + TCompiler* compiler = base->getAsCompiler(); + if (!compiler) return; - return success ? 1 : 0; + 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; + + default: UNREACHABLE(); + } } // // Return any compiler log of messages for the application. // -const char* ShGetInfoLog(const ShHandle handle) +void ShGetInfoLog(const ShHandle handle, char* infoLog) { - if (!InitThread()) - return 0; - - if (handle == 0) - return 0; + if (!handle || !infoLog) + return; TShHandleBase* base = static_cast(handle); - TInfoSink* infoSink = 0; - - if (base->getAsCompiler()) - infoSink = &(base->getAsCompiler()->getInfoSink()); + TCompiler* compiler = base->getAsCompiler(); + if (!compiler) return; - infoSink->info << infoSink->debug.c_str(); - return infoSink->info.c_str(); + TInfoSink& infoSink = compiler->getInfoSink(); + strcpy(infoLog, infoSink.info.c_str()); } // // Return any object code. // -const char* ShGetObjectCode(const ShHandle handle) +void ShGetObjectCode(const ShHandle handle, char* objCode) { - if (!InitThread()) - return 0; - - if (handle == 0) - return 0; + if (!handle || !objCode) + return; TShHandleBase* base = static_cast(handle); - TInfoSink* infoSink; + TCompiler* compiler = base->getAsCompiler(); + if (!compiler) return; - if (base->getAsCompiler()) - infoSink = &(base->getAsCompiler()->getInfoSink()); + TInfoSink& infoSink = compiler->getInfoSink(); + strcpy(objCode, infoSink.obj.c_str()); +} - return infoSink->obj.c_str(); +void ShGetActiveAttrib(const ShHandle handle, + int index, + int* length, + int* size, + ShDataType* type, + char* name) +{ + getVariableInfo(SH_ACTIVE_ATTRIBUTES, + handle, index, length, size, type, name); +} + +void ShGetActiveUniform(const ShHandle handle, + int index, + int* length, + int* size, + ShDataType* type, + char* name) +{ + getVariableInfo(SH_ACTIVE_UNIFORMS, + handle, index, length, size, type, name); } diff --git a/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.cpp b/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.cpp index 1b08667..02817d4 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.cpp @@ -140,6 +140,22 @@ void TSymbolTableLevel::relateToOperator(const char* name, TOperator 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(it->second); + if (function->getName() == name) + function->relateToExtension(ext); + } + } +} TSymbol::TSymbol(const TSymbol& copyOf) { diff --git a/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.h b/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.h index b1a80b5..38bc657 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.h +++ b/Source/ThirdParty/ANGLE/src/compiler/SymbolTable.h @@ -94,7 +94,10 @@ public: void shareConstPointer( ConstantUnion *constArray) { - delete unionArray; + if (unionArray == constArray) + return; + + delete[] unionArray; unionArray = constArray; } TVariable(const TVariable&, TStructureMap& remapper); // copy constructor @@ -156,14 +159,18 @@ public: 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(parameters.size()); } - TParameter& operator [](int i) { return parameters[i]; } - const TParameter& operator [](int i) const { return parameters[i]; } + int getParamCount() const { return static_cast(parameters.size()); } + const TParameter& getParam(int i) const { return parameters[i]; } virtual void dump(TInfoSink &infoSink) const; TFunction(const TFunction&, TStructureMap& remapper); @@ -175,6 +182,7 @@ protected: TType returnType; TString mangledName; TOperator op; + TString extension; bool defined; }; @@ -221,6 +229,7 @@ public: } void relateToOperator(const char* name, TOperator op); + void relateToExtension(const char* name, const TString& ext); void dump(TInfoSink &infoSink) const; TSymbolTableLevel* clone(TStructureMap& remapper); @@ -289,8 +298,16 @@ public: return symbol; } - TSymbolTableLevel* getGlobalLevel() { assert(table.size() >= 2); return table[1]; } - void relateToOperator(const char* name, TOperator op) { table[0]->relateToOperator(name, op); } + 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); diff --git a/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.cpp index 7b8d903..7a63ae1 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.cpp @@ -7,14 +7,31 @@ #include "compiler/TranslatorGLSL.h" #include "compiler/OutputGLSL.h" +#include "compiler/VersionGLSL.h" -TranslatorGLSL::TranslatorGLSL(EShLanguage lang, EShSpec spec) - : TCompiler(lang, spec) { +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"; + } } -bool TranslatorGLSL::compile(TIntermNode* root) { - TOutputGLSL outputGLSL(infoSink.obj); - root->traverse(&outputGLSL); +TranslatorGLSL::TranslatorGLSL(ShShaderType type, ShShaderSpec spec) + : TCompiler(type, spec) { +} + +void TranslatorGLSL::translate(TIntermNode* root) { + TInfoSinkBase& sink = getInfoSink().obj; - return true; + // 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 index 973e39a..c2ce06d 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.h +++ b/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.h @@ -11,8 +11,10 @@ class TranslatorGLSL : public TCompiler { public: - TranslatorGLSL(EShLanguage lang, EShSpec spec); - virtual bool compile(TIntermNode* root); + 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 index 3a1e52d..96d7f10 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.cpp @@ -8,17 +8,15 @@ #include "compiler/OutputHLSL.h" -TranslatorHLSL::TranslatorHLSL(EShLanguage lang, EShSpec spec) - : TCompiler(lang, spec) +TranslatorHLSL::TranslatorHLSL(ShShaderType type, ShShaderSpec spec) + : TCompiler(type, spec) { } -bool TranslatorHLSL::compile(TIntermNode *root) +void TranslatorHLSL::translate(TIntermNode *root) { TParseContext& parseContext = *GetGlobalParseContext(); sh::OutputHLSL outputHLSL(parseContext); outputHLSL.output(); - - return true; } diff --git a/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.h b/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.h index 38a5f0c..c3f672b 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.h +++ b/Source/ThirdParty/ANGLE/src/compiler/TranslatorHLSL.h @@ -11,8 +11,10 @@ class TranslatorHLSL : public TCompiler { public: - TranslatorHLSL(EShLanguage lang, EShSpec spec); - virtual bool compile(TIntermNode* root); + 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 index 897b28f..d0fcc08 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/Types.h +++ b/Source/ThirdParty/ANGLE/src/compiler/Types.h @@ -85,12 +85,12 @@ public: TType() {} TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) : type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), - structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0) + 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), - structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0) + maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), fieldName(0), mangled(0), typeName(0) { if (p.userDef) { structure = p.userDef->getStruct(); @@ -99,7 +99,7 @@ public: } TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) : type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), - structure(userDef), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0) + maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), fieldName(0), mangled(0) { typeName = NewPoolTString(n.c_str()); } diff --git a/Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.cpp b/Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.cpp index 20035fe..a36c393 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.cpp @@ -3,6 +3,8 @@ // 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" @@ -44,7 +46,7 @@ bool UnfoldSelect::visitSelection(Visit visit, TIntermSelection *node) "}\n" "else\n" "{\n"; - node->getCondition()->traverse(this); + node->getFalseBlock()->traverse(this); out << " t" << i << " = "; node->getFalseBlock()->traverse(mOutputHLSL); out << ";\n" diff --git a/Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.h b/Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.h index 68b2e8a..de296e4 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.h +++ b/Source/ThirdParty/ANGLE/src/compiler/UnfoldSelect.h @@ -3,6 +3,8 @@ // 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_ diff --git a/Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.cpp b/Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.cpp new file mode 100644 index 0000000..886f693 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.cpp @@ -0,0 +1,468 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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; +} + +// 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; +}; +} // 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: + case EOpIndexIndirect: + 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)); + 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 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(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 0000000..a4f5a28 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.h @@ -0,0 +1,62 @@ +// +// 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; +}; +typedef TVector 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 0000000..ad2e08f --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/VariableInfo.cpp @@ -0,0 +1,210 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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, + TVariableInfoList& infoList); +static void getUserDefinedVariableInfo(const TType& type, + const TString& name, + TVariableInfoList& infoList); + +// Returns info for an attribute or uniform. +static void getVariableInfo(const TType& type, + const TString& name, + TVariableInfoList& infoList) +{ + if (type.getBasicType() == EbtStruct) { + if (type.isArray()) { + for (int i = 0; i < type.getArraySize(); ++i) { + TString lname = name + arrayBrackets(i); + getUserDefinedVariableInfo(type, lname, infoList); + } + } else { + getUserDefinedVariableInfo(type, name, infoList); + } + } else { + getBuiltInVariableInfo(type, name, infoList); + } +} + +void getBuiltInVariableInfo(const TType& type, + const TString& name, + TVariableInfoList& infoList) +{ + ASSERT(type.getBasicType() != EbtStruct); + + TVariableInfo varInfo; + if (type.isArray()) { + varInfo.name = (name + "[0]").c_str(); + varInfo.size = type.getArraySize(); + } else { + varInfo.name = name.c_str(); + varInfo.size = 1; + } + varInfo.type = getVariableDataType(type); + infoList.push_back(varInfo); +} + +void getUserDefinedVariableInfo(const TType& type, + const TString& name, + TVariableInfoList& infoList) +{ + ASSERT(type.getBasicType() == EbtStruct); + + TString lname = name + "."; + const TTypeList* structure = type.getStruct(); + for (size_t i = 0; i < structure->size(); ++i) { + const TType* fieldType = (*structure)[i].type; + getVariableInfo(*fieldType, + lname + 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->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 0000000..15a5c57 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/VariableInfo.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "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; + ShDataType type; + int size; +}; +typedef std::vector 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; +}; + diff --git a/Source/ThirdParty/ANGLE/src/compiler/VersionGLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/VersionGLSL.cpp new file mode 100644 index 0000000..3f87820 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/VersionGLSL.cpp @@ -0,0 +1,108 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/VersionGLSL.h" + +static const int GLSL_VERSION_110 = 110; +static const int GLSL_VERSION_120 = 120; + +// We need to scan for two 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. +// So we need to scan the entire fragment shader but only the global scope +// of vertex shader. +// +// 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) +{ + ASSERT(mShaderType == SH_FRAGMENT_SHADER); + + if (node->getSymbol() == "gl_PointCoord") + updateVersion(GLSL_VERSION_120); +} + +void TVersionGLSL::visitConstantUnion(TIntermConstantUnion*) +{ + ASSERT(mShaderType == SH_FRAGMENT_SHADER); +} + +bool TVersionGLSL::visitBinary(Visit, TIntermBinary*) +{ + ASSERT(mShaderType == SH_FRAGMENT_SHADER); + return true; +} + +bool TVersionGLSL::visitUnary(Visit, TIntermUnary*) +{ + ASSERT(mShaderType == SH_FRAGMENT_SHADER); + return true; +} + +bool TVersionGLSL::visitSelection(Visit, TIntermSelection*) +{ + ASSERT(mShaderType == SH_FRAGMENT_SHADER); + return true; +} + +bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate* node) +{ + // We need to scan the entire fragment shader but only the global scope + // of vertex shader. + bool visitChildren = mShaderType == SH_FRAGMENT_SHADER ? true : false; + + 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; + } + default: break; + } + + return visitChildren; +} + +bool TVersionGLSL::visitLoop(Visit, TIntermLoop*) +{ + ASSERT(mShaderType == SH_FRAGMENT_SHADER); + return true; +} + +bool TVersionGLSL::visitBranch(Visit, TIntermBranch*) +{ + ASSERT(mShaderType == SH_FRAGMENT_SHADER); + 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 0000000..64d002b --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/VersionGLSL.h @@ -0,0 +1,50 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#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. +// +class TVersionGLSL : public TIntermTraverser { +public: + TVersionGLSL(ShShaderType type); + + // Returns 120 if "invariant" keyword or "gl_PointCoord" is 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/generate_glslang_lexer.sh b/Source/ThirdParty/ANGLE/src/compiler/generate_glslang_lexer.sh new file mode 100644 index 0000000..268479d --- /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 0000000..889f5c0 --- /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 0000000..26f1457 --- /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 index 02c226f..5a7c5d5 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/glslang.l +++ b/Source/ThirdParty/ANGLE/src/compiler/glslang.l @@ -4,34 +4,29 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -*/ -/* Based on -ANSI C grammar, Lex specification - -In 1985, Jeff Lee published this Lex specification together with a Yacc -grammar for the April 30, 1985 ANSI C draft. Tom Stockfisch reposted -both to net.sources in 1987; that original, as mentioned in the answer -to question 17.25 of the comp.lang.c FAQ, can be ftp'ed from ftp.uu.net, -file usenet/net.sources/ansi.c.grammar.Z. -I intend to keep this version as close to the current C Standard grammar -as possible; please let me know if you discover discrepancies. +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 -Jutta Degener, 1995 +IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_glslang_lexer.sh, +WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). */ -D [0-9] -L [a-zA-Z_] -H [a-fA-F0-9] -E [Ee][+-]?{D}+ -O [0-7] +%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. +// -%option nounput -%{ -#include -#include +// 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 */ @@ -39,407 +34,304 @@ O [0-7] #pragma warning(disable : 4102) #endif -int yy_input(char* buf, int max_size); - -extern int yyparse(void*); -#define YY_DECL int yylex(YYSTYPE* pyylval, void* parseContextLocal) -#define parseContext (*((TParseContext*)(parseContextLocal))) - -#define YY_INPUT(buf,result,max_size) (result = yy_input(buf, max_size)) +#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); %} -/* -TODO(alokp): yylineno is only here to support old flex.exe in compiler/tools. -Remove it when we can exclusively use the newer version. -*/ -%option yylineno - -%option noyywrap -%option never-interactive -%x FIELDS +%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] %% -<*>"//"[^\n]*"\n" { /* ?? carriage and/or line-feed? */ }; - -"invariant" { pyylval->lex.line = yylineno; return(INVARIANT); } -"highp" { pyylval->lex.line = yylineno; return(HIGH_PRECISION); } -"mediump" { pyylval->lex.line = yylineno; return(MEDIUM_PRECISION); } -"lowp" { pyylval->lex.line = yylineno; return(LOW_PRECISION); } -"precision" { pyylval->lex.line = yylineno; return(PRECISION); } - -"attribute" { pyylval->lex.line = yylineno; return(ATTRIBUTE); } -"const" { pyylval->lex.line = yylineno; return(CONST_QUAL); } -"uniform" { pyylval->lex.line = yylineno; return(UNIFORM); } -"varying" { pyylval->lex.line = yylineno; return(VARYING); } - -"break" { pyylval->lex.line = yylineno; return(BREAK); } -"continue" { pyylval->lex.line = yylineno; return(CONTINUE); } -"do" { pyylval->lex.line = yylineno; return(DO); } -"for" { pyylval->lex.line = yylineno; return(FOR); } -"while" { pyylval->lex.line = yylineno; return(WHILE); } - -"if" { pyylval->lex.line = yylineno; return(IF); } -"else" { pyylval->lex.line = yylineno; return(ELSE); } - -"in" { pyylval->lex.line = yylineno; return(IN_QUAL); } -"out" { pyylval->lex.line = yylineno; return(OUT_QUAL); } -"inout" { pyylval->lex.line = yylineno; return(INOUT_QUAL); } - -"float" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(FLOAT_TYPE); } -"int" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(INT_TYPE); } -"void" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(VOID_TYPE); } -"bool" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(BOOL_TYPE); } -"true" { pyylval->lex.line = yylineno; pyylval->lex.b = true; return(BOOLCONSTANT); } -"false" { pyylval->lex.line = yylineno; pyylval->lex.b = false; return(BOOLCONSTANT); } - -"discard" { pyylval->lex.line = yylineno; return(DISCARD); } -"return" { pyylval->lex.line = yylineno; return(RETURN); } - -"mat2" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX2); } -"mat3" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX3); } -"mat4" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX4); } - -"vec2" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC2); } -"vec3" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC3); } -"vec4" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC4); } -"ivec2" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC2); } -"ivec3" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC3); } -"ivec4" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC4); } -"bvec2" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC2); } -"bvec3" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC3); } -"bvec4" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC4); } - -"sampler2D" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER2D; } -"samplerCube" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLERCUBE; } - -"struct" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(STRUCT); } - -"asm" { PaReservedWord(); return 0; } - -"class" { PaReservedWord(); return 0; } -"union" { PaReservedWord(); return 0; } -"enum" { PaReservedWord(); return 0; } -"typedef" { PaReservedWord(); return 0; } -"template" { PaReservedWord(); return 0; } -"this" { PaReservedWord(); return 0; } -"packed" { PaReservedWord(); return 0; } - -"goto" { PaReservedWord(); return 0; } -"switch" { PaReservedWord(); return 0; } -"default" { PaReservedWord(); return 0; } - -"inline" { PaReservedWord(); return 0; } -"noinline" { PaReservedWord(); return 0; } -"volatile" { PaReservedWord(); return 0; } -"public" { PaReservedWord(); return 0; } -"static" { PaReservedWord(); return 0; } -"extern" { PaReservedWord(); return 0; } -"external" { PaReservedWord(); return 0; } -"interface" { PaReservedWord(); return 0; } - -"long" { PaReservedWord(); return 0; } -"short" { PaReservedWord(); return 0; } -"double" { PaReservedWord(); return 0; } -"half" { PaReservedWord(); return 0; } -"fixed" { PaReservedWord(); return 0; } -"unsigned" { PaReservedWord(); return 0; } - -"input" { PaReservedWord(); return 0; } -"output" { PaReservedWord(); return 0; } - -"hvec2" { PaReservedWord(); return 0; } -"hvec3" { PaReservedWord(); return 0; } -"hvec4" { PaReservedWord(); return 0; } -"fvec2" { PaReservedWord(); return 0; } -"fvec3" { PaReservedWord(); return 0; } -"fvec4" { PaReservedWord(); return 0; } -"dvec2" { PaReservedWord(); return 0; } -"dvec3" { PaReservedWord(); return 0; } -"dvec4" { PaReservedWord(); return 0; } - -"sizeof" { PaReservedWord(); return 0; } -"cast" { PaReservedWord(); return 0; } - -"namespace" { PaReservedWord(); return 0; } -"using" { PaReservedWord(); return 0; } - -{L}({L}|{D})* { - pyylval->lex.line = yylineno; - pyylval->lex.string = NewPoolTString(yytext); - return PaIdentOrType(*pyylval->lex.string, parseContext, pyylval->lex.symbol); + +%{ + TParseContext* context = yyextra; +%} + + /* Single-line comments */ +"//"[^\n]* ; + + /* Multi-line comments */ +"/*" { yy_push_state(COMMENT, yyscanner); } +. | +\n ; +"*/" { 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}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } -0{O}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } -0{D}+ { pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); parseContext.recover(); return 0;} -{D}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } - -{D}+{E} { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast(atof(yytext)); return(FLOATCONSTANT); } -{D}+"."{D}*({E})? { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast(atof(yytext)); return(FLOATCONSTANT); } -"."{D}+({E})? { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast(atof(yytext)); return(FLOATCONSTANT); } - -"/*" { int ret = PaParseComment(pyylval->lex.line, parseContext); if (!ret) return ret; } - -"+=" { pyylval->lex.line = yylineno; return(ADD_ASSIGN); } -"-=" { pyylval->lex.line = yylineno; return(SUB_ASSIGN); } -"*=" { pyylval->lex.line = yylineno; return(MUL_ASSIGN); } -"/=" { pyylval->lex.line = yylineno; return(DIV_ASSIGN); } -"%=" { pyylval->lex.line = yylineno; return(MOD_ASSIGN); } -"<<=" { pyylval->lex.line = yylineno; return(LEFT_ASSIGN); } -">>=" { pyylval->lex.line = yylineno; return(RIGHT_ASSIGN); } -"&=" { pyylval->lex.line = yylineno; return(AND_ASSIGN); } -"^=" { pyylval->lex.line = yylineno; return(XOR_ASSIGN); } -"|=" { pyylval->lex.line = yylineno; return(OR_ASSIGN); } - -"++" { pyylval->lex.line = yylineno; return(INC_OP); } -"--" { pyylval->lex.line = yylineno; return(DEC_OP); } -"&&" { pyylval->lex.line = yylineno; return(AND_OP); } -"||" { pyylval->lex.line = yylineno; return(OR_OP); } -"^^" { pyylval->lex.line = yylineno; return(XOR_OP); } -"<=" { pyylval->lex.line = yylineno; return(LE_OP); } -">=" { pyylval->lex.line = yylineno; return(GE_OP); } -"==" { pyylval->lex.line = yylineno; return(EQ_OP); } -"!=" { pyylval->lex.line = yylineno; return(NE_OP); } -"<<" { pyylval->lex.line = yylineno; return(LEFT_OP); } -">>" { pyylval->lex.line = yylineno; return(RIGHT_OP); } -";" { pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(SEMICOLON); } -("{"|"<%") { pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(LEFT_BRACE); } -("}"|"%>") { pyylval->lex.line = yylineno; return(RIGHT_BRACE); } -"," { pyylval->lex.line = yylineno; if (parseContext.inTypeParen) parseContext.lexAfterType = false; return(COMMA); } -":" { pyylval->lex.line = yylineno; return(COLON); } -"=" { pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(EQUAL); } -"(" { pyylval->lex.line = yylineno; parseContext.lexAfterType = false; parseContext.inTypeParen = true; return(LEFT_PAREN); } -")" { pyylval->lex.line = yylineno; parseContext.inTypeParen = false; return(RIGHT_PAREN); } -("["|"<:") { pyylval->lex.line = yylineno; return(LEFT_BRACKET); } -("]"|":>") { pyylval->lex.line = yylineno; return(RIGHT_BRACKET); } +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(atof_dot(yytext)); return(FLOATCONSTANT); } +{D}+"."{D}*({E})? { yylval->lex.f = static_cast(atof_dot(yytext)); return(FLOATCONSTANT); } +"."{D}+({E})? { yylval->lex.f = static_cast(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); } -"!" { pyylval->lex.line = yylineno; return(BANG); } -"-" { pyylval->lex.line = yylineno; return(DASH); } -"~" { pyylval->lex.line = yylineno; return(TILDE); } -"+" { pyylval->lex.line = yylineno; return(PLUS); } -"*" { pyylval->lex.line = yylineno; return(STAR); } -"/" { pyylval->lex.line = yylineno; return(SLASH); } -"%" { pyylval->lex.line = yylineno; return(PERCENT); } -"<" { pyylval->lex.line = yylineno; return(LEFT_ANGLE); } -">" { pyylval->lex.line = yylineno; return(RIGHT_ANGLE); } -"|" { pyylval->lex.line = yylineno; return(VERTICAL_BAR); } -"^" { pyylval->lex.line = yylineno; return(CARET); } -"&" { pyylval->lex.line = yylineno; return(AMPERSAND); } -"?" { pyylval->lex.line = yylineno; return(QUESTION); } +"!" { 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); } {L}({L}|{D})* { -BEGIN(INITIAL); - pyylval->lex.line = yylineno; - pyylval->lex.string = NewPoolTString(yytext); - return FIELD_SELECTION; } + BEGIN(INITIAL); + yylval->lex.string = NewPoolTString(yytext); + return FIELD_SELECTION; +} [ \t\v\f\r] {} [ \t\v\n\f\r] { } -<*><> { (&parseContext)->AfterEOF = true; yy_delete_buffer(YY_CURRENT_BUFFER); yyterminate();} -<*>. { parseContext.infoSink.info << "FLEX: Unknown char " << yytext << "\n"; - return 0; } +<*><> { context->AfterEOF = true; yyterminate(); } +<*>. { context->warning(yylineno, "Unknown char", yytext, ""); return 0; } %% - -//Including Pre-processor. extern "C" { - #include "compiler/preprocessor/preprocess.h" -} - -// -// The YY_INPUT macro just calls this. Maybe this could be just put into -// the macro directly. -// - -int yy_input(char* buf, int max_size) -{ - int len; - - if ((len = yylex_CPP(buf, max_size)) == 0) - return 0; - if (len >= max_size) - YY_FATAL_ERROR( "input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); - - buf[len] = ' '; - return len+1; -} - - -// -// Parse an array of strings using yyparse. We set up globals used by -// yywrap. -// -// Returns 0 for success, as per yyparse(). -// -int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseContextLocal) -{ - int argv0len; - - ScanFromString(argv[0]); - - //Storing the Current Compiler Parse context into the cpp structure. - cpp->pC = (void*)&parseContextLocal; - - if (!argv || argc == 0) - return 1; - - for (int i = 0; i < argc; ++i) { - if (!argv[i]) { - parseContextLocal.error(0, "Null shader source string", "", ""); - parseContextLocal.recover(); - return 1; - } - } - - if (!strLen) { - argv0len = (int) strlen(argv[0]); - strLen = &argv0len; - } - yyrestart(0); - (&parseContextLocal)->AfterEOF = false; - cpp->PaWhichStr = 0; - cpp->PaArgv = argv; - cpp->PaArgc = argc; - cpp->PaStrLen = strLen; - cpp->pastFirstStatement = 0; - yylineno = 1; - - if (*cpp->PaStrLen >= 0) { - int ret = yyparse((void*)(&parseContextLocal)); - if (ret || cpp->CompileError == 1 || parseContextLocal.recoveredFromError || parseContextLocal.numErrors > 0) - return 1; - else - return 0; - } - else - return 0; -} - -void yyerror(const char *s) -{ - if (((TParseContext *)cpp->pC)->AfterEOF) { - if (cpp->tokensBeforeEOF == 1) { - GlobalParseContext->error(yylineno, "syntax error", "pre-mature EOF", s, ""); - GlobalParseContext->recover(); - } - } else { - GlobalParseContext->error(yylineno, "syntax error", yytext, s, ""); - GlobalParseContext->recover(); - } -} +// Preprocessor interface. +#include "compiler/preprocessor/preprocess.h" -void PaReservedWord() -{ - GlobalParseContext->error(yylineno, "Reserved word.", yytext, "", ""); - GlobalParseContext->recover(); -} - -int PaIdentOrType(TString& id, TParseContext& parseContextLocal, TSymbol*& symbol) -{ - symbol = parseContextLocal.symbolTable.find(id); - if (parseContextLocal.lexAfterType == false && symbol && symbol->isVariable()) { - TVariable* variable = static_cast(symbol); - if (variable->isUserType()) { - parseContextLocal.lexAfterType = true; - return TYPE_NAME; - } - } - - return IDENTIFIER; -} - -int PaParseComment(int &lineno, TParseContext& parseContextLocal) -{ - int transitionFlag = 0; - int nextChar; - - while (transitionFlag != 2) { - nextChar = yyinput(); - if (nextChar == '\n') - lineno++; - switch (nextChar) { - case '*' : - transitionFlag = 1; - break; - case '/' : /* if star is the previous character, then it is the end of comment */ - if (transitionFlag == 1) { - return 1 ; - } - break; - case EOF : - /* Raise error message here */ - parseContextLocal.error(yylineno, "End of shader found before end of comment.", "", "", ""); - GlobalParseContext->recover(); - return YY_NULL; - default : /* Any other character will be a part of the comment */ - transitionFlag = 0; - } - } - return 1; -} - -extern "C" { +#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) { - ((TParseContext *)cpp->pC)->infoSink.debug.message(EPrefixNone, msg); + SETUP_CONTEXT(cpp); + context->infoSink.debug.message(EPrefixNone, msg); } void CPPWarningToInfoLog(const char *msg) { - ((TParseContext *)cpp->pC)->infoSink.info.message(EPrefixWarning, msg, yylineno); + SETUP_CONTEXT(cpp); + context->warning(yylineno, msg, "", ""); } void CPPShInfoLogMsg(const char *msg) { - ((TParseContext *)cpp->pC)->error(yylineno,"", "",msg,""); - GlobalParseContext->recover(); + SETUP_CONTEXT(cpp); + context->error(yylineno, msg, "", ""); + context->recover(); } void CPPErrorToInfoLog(char *msg) { - ((TParseContext *)cpp->pC)->error(yylineno,"syntax error", "",msg,""); - GlobalParseContext->recover(); + SETUP_CONTEXT(cpp); + context->error(yylineno, msg, "", ""); + context->recover(); } void SetLineNumber(int line) { - yylineno &= ~SourceLocLineMask; - yylineno |= line; + SETUP_CONTEXT(cpp); + int string = 0; + DecodeSourceLoc(yylineno, &string, NULL); + yylineno = EncodeSourceLoc(string, line); } void SetStringNumber(int string) { - yylineno = (string << SourceLocStringShift) | (yylineno & SourceLocLineMask); + SETUP_CONTEXT(cpp); + int line = 0; + DecodeSourceLoc(yylineno, NULL, &line); + yylineno = EncodeSourceLoc(string, line); } -int GetStringNumber(void) +int GetStringNumber() { - return yylineno >> 16; + SETUP_CONTEXT(cpp); + int string = 0; + DecodeSourceLoc(yylineno, &string, NULL); + return string; } -int GetLineNumber(void) +int GetLineNumber() { - return yylineno & SourceLocLineMask; + SETUP_CONTEXT(cpp); + int line = 0; + DecodeSourceLoc(yylineno, NULL, &line); + return line; } -void IncLineNumber(void) +void IncLineNumber() { - if ((yylineno & SourceLocLineMask) <= SourceLocLineMask) - ++yylineno; + SETUP_CONTEXT(cpp); + int string = 0, line = 0; + DecodeSourceLoc(yylineno, &string, &line); + yylineno = EncodeSourceLoc(string, ++line); } -void DecLineNumber(void) +void DecLineNumber() { - if ((yylineno & SourceLocLineMask) > 0) - --yylineno; + 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"); @@ -452,9 +344,9 @@ void HandlePragma(const char **tokens, int numTokens) } if (!strcmp(tokens[2], "on")) - ((TParseContext *)cpp->pC)->contextPragma.optimize = true; + context->contextPragma.optimize = true; else if (!strcmp(tokens[2], "off")) - ((TParseContext *)cpp->pC)->contextPragma.optimize = false; + context->contextPragma.optimize = false; else { CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'optimize' pragma"); return; @@ -476,9 +368,9 @@ void HandlePragma(const char **tokens, int numTokens) } if (!strcmp(tokens[2], "on")) - ((TParseContext *)cpp->pC)->contextPragma.debug = true; + context->contextPragma.debug = true; else if (!strcmp(tokens[2], "off")) - ((TParseContext *)cpp->pC)->contextPragma.debug = false; + context->contextPragma.debug = false; else { CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'debug' pragma"); return; @@ -489,7 +381,6 @@ void HandlePragma(const char **tokens, int numTokens) return; } } else { - #ifdef PRAGMA_TABLE // // implementation specific pragma @@ -524,21 +415,24 @@ void HandlePragma(const char **tokens, int numTokens) void StoreStr(char *string) { + SETUP_CONTEXT(cpp); TString strSrc; strSrc = TString(string); - ((TParseContext *)cpp->pC)->HashErrMsg = ((TParseContext *)cpp->pC)->HashErrMsg + " " + strSrc; + context->HashErrMsg = context->HashErrMsg + " " + strSrc; } const char* GetStrfromTStr(void) { - cpp->ErrMsg = (((TParseContext *)cpp->pC)->HashErrMsg).c_str(); + SETUP_CONTEXT(cpp); + cpp->ErrMsg = context->HashErrMsg.c_str(); return cpp->ErrMsg; } void ResetTString(void) { - ((TParseContext *)cpp->pC)->HashErrMsg = ""; + SETUP_CONTEXT(cpp); + context->HashErrMsg = ""; } TBehavior GetBehavior(const char* behavior) @@ -557,8 +451,9 @@ TBehavior GetBehavior(const char* behavior) } } -void updateExtensionBehavior(const char* extName, const char* behavior) +void updateExtensionBehavior(const char* extName, const char* behavior) { + SETUP_CONTEXT(cpp); TBehavior behaviorVal = GetBehavior(behavior); TMap:: iterator iter; TString msg; @@ -569,12 +464,12 @@ void updateExtensionBehavior(const char* extName, const char* behavior) CPPShInfoLogMsg("extension 'all' cannot have 'require' or 'enable' behavior"); return; } else { - for (iter = ((TParseContext *)cpp->pC)->extensionBehavior.begin(); iter != ((TParseContext *)cpp->pC)->extensionBehavior.end(); ++iter) + for (iter = context->extensionBehavior.begin(); iter != context->extensionBehavior.end(); ++iter) iter->second = behaviorVal; } } else { - iter = ((TParseContext *)cpp->pC)->extensionBehavior.find(TString(extName)); - if (iter == ((TParseContext *)cpp->pC)->extensionBehavior.end()) { + iter = context->extensionBehavior.find(TString(extName)); + if (iter == context->extensionBehavior.end()) { switch (behaviorVal) { case EBhRequire: CPPShInfoLogMsg((TString("extension '") + extName + "' is not supported").c_str()); @@ -583,7 +478,7 @@ void updateExtensionBehavior(const char* extName, const char* behavior) case EBhWarn: case EBhDisable: msg = TString("extension '") + extName + "' is not supported"; - ((TParseContext *)cpp->pC)->infoSink.info.message(EPrefixWarning, msg.c_str(), yylineno); + context->infoSink.info.message(EPrefixWarning, msg.c_str(), yylineno); break; } return; @@ -591,10 +486,85 @@ void updateExtensionBehavior(const char* extName, const char* behavior) iter->second = behaviorVal; } } - } // extern "C" -void setInitialState() -{ - yy_start = 1; +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(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 index d0d29df..5eae4b5 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/glslang.y +++ b/Source/ThirdParty/ANGLE/src/compiler/glslang.y @@ -1,89 +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. // -/** - * This is bison grammar and production code for parsing the OpenGL 2.0 shading - * languages. - */ -%{ - -/* Based on: -ANSI C Yacc grammar +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 -In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a -matching Lex specification) for the April 30, 1985 draft version of the -ANSI C standard. Tom Stockfisch reposted it to net.sources in 1987; that -original, as mentioned in the answer to question 17.25 of the comp.lang.c -FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z. +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). +*/ -I intend to keep this version as close to the current C Standard grammar as -possible; please let me know if you discover discrepancies. +%{ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// -Jutta Degener, 1995 -*/ +// 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 YYPARSE_PARAM parseContextLocal -/* -TODO(alokp): YYPARSE_PARAM_DECL is only here to support old bison.exe in -compiler/tools. Remove it when we can exclusively use the newer version. -*/ -#define YYPARSE_PARAM_DECL void* -#define parseContext ((TParseContext*)(parseContextLocal)) -#define YYLEX_PARAM parseContextLocal -#define YY_DECL int yylex(YYSTYPE* pyylval, void* parseContextLocal) -extern void yyerror(const char*); - -#define FRAG_VERT_ONLY(S, L) { \ - if (parseContext->language != EShLangFragment && \ - parseContext->language != EShLangVertex) { \ - parseContext->error(L, " supported in vertex/fragment shaders only ", S, "", ""); \ - parseContext->recover(); \ - } \ -} - -#define VERTEX_ONLY(S, L) { \ - if (parseContext->language != EShLangVertex) { \ - parseContext->error(L, " supported in vertex shaders only ", S, "", ""); \ - parseContext->recover(); \ - } \ -} - -#define FRAG_ONLY(S, L) { \ - if (parseContext->language != EShLangFragment) { \ - parseContext->error(L, " supported in fragment shaders only ", S, "", ""); \ - parseContext->recover(); \ - } \ -} - -#define PACK_ONLY(S, L) { \ - if (parseContext->language != EShLangPack) { \ - parseContext->error(L, " supported in pack shaders only ", S, "", ""); \ - parseContext->recover(); \ - } \ -} +#define YYLEX_PARAM context->scanner +%} -#define UNPACK_ONLY(S, L) { \ - if (parseContext->language != EShLangUnpack) { \ - parseContext->error(L, " supported in unpack shaders only ", S, "", ""); \ - parseContext->recover(); \ - } \ -} +%expect 1 /* One shift reduce conflict because of if | else */ +%pure-parser +%parse-param {TParseContext* context} -#define PACK_UNPACK_ONLY(S, L) { \ - if (parseContext->language != EShLangUnpack && \ - parseContext->language != EShLangPack) { \ - parseContext->error(L, " supported in pack/unpack shaders only ", S, "", ""); \ - parseContext->recover(); \ - } \ -} -%} %union { struct { TSourceLoc line; @@ -117,11 +66,32 @@ extern void yyerror(const char*); } %{ - extern int yylex(YYSTYPE*, void*); +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(); \ + } \ +} %} -%pure_parser /* Just in case is called from multiple threads */ -%expect 1 /* One shift reduce conflict because of if | else */ %token INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION %token ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE %token BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN @@ -185,17 +155,17 @@ variable_identifier const TSymbol* symbol = $1.symbol; const TVariable* variable; if (symbol == 0) { - parseContext->error($1.line, "undeclared identifier", $1.string->c_str(), ""); - parseContext->recover(); + context->error($1.line, "undeclared identifier", $1.string->c_str(), ""); + context->recover(); TType type(EbtFloat, EbpUndefined); TVariable* fakeVariable = new TVariable($1.string, type); - parseContext->symbolTable.insert(*fakeVariable); + context->symbolTable.insert(*fakeVariable); variable = fakeVariable; } else { // This identifier can only be a variable type symbol if (! symbol->isVariable()) { - parseContext->error($1.line, "variable expected", $1.string->c_str(), ""); - parseContext->recover(); + context->error($1.line, "variable expected", $1.string->c_str(), ""); + context->recover(); } variable = static_cast(symbol); } @@ -206,9 +176,9 @@ variable_identifier if (variable->getType().getQualifier() == EvqConst ) { ConstantUnion* constArray = variable->getConstPointer(); TType t(variable->getType()); - $$ = parseContext->intermediate.addConstantUnion(constArray, t, $1.line); + $$ = context->intermediate.addConstantUnion(constArray, t, $1.line); } else - $$ = parseContext->intermediate.addSymbol(variable->getUniqueId(), + $$ = context->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), $1.line); } @@ -224,22 +194,22 @@ primary_expression // check for overflow for constants // if (abs($1.i) >= (1 << 16)) { - parseContext->error($1.line, " integer constant overflow", "", ""); - parseContext->recover(); + context->error($1.line, " integer constant overflow", "", ""); + context->recover(); } ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setIConst($1.i); - $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $1.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $1.line); } | FLOATCONSTANT { ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setFConst($1.f); - $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line); } | BOOLCONSTANT { ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst($1.b); - $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $1.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $1.line); } | LEFT_PAREN expression RIGHT_PAREN { $$ = $2; @@ -253,57 +223,57 @@ postfix_expression | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET { if (!$1->isArray() && !$1->isMatrix() && !$1->isVector()) { if ($1->getAsSymbolNode()) - parseContext->error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str(), ""); + context->error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str(), ""); else - parseContext->error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression", ""); - parseContext->recover(); + 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 - $$ = parseContext->addConstArrayNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line); + $$ = 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 - $$ = parseContext->addConstVectorNode(fields, $1, $2.line); + $$ = context->addConstVectorNode(fields, $1, $2.line); } else if ($1->isMatrix()) { // constant folding for matrices - $$ = parseContext->addConstMatrixNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line); + $$ = 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() ) { - parseContext->error($2.line, "", "[", "field selection out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()); - parseContext->recover(); + 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 (parseContext->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, $2.line)) - parseContext->recover(); + if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, $2.line)) + context->recover(); } else { - if (parseContext->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line)) - parseContext->recover(); + if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line)) + context->recover(); } } else if ( $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= $1->getType().getArraySize()) { - parseContext->error($2.line, "", "[", "array index out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()); - parseContext->recover(); + context->error($2.line, "", "[", "array index out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()); + context->recover(); } } - $$ = parseContext->intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line); + $$ = context->intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line); } } else { if ($1->isArray() && $1->getType().getArraySize() == 0) { - parseContext->error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable"); - parseContext->recover(); + context->error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable"); + context->recover(); } - $$ = parseContext->intermediate.addIndex(EOpIndexIndirect, $1, $3, $2.line); + $$ = context->intermediate.addIndex(EOpIndexIndirect, $1, $3, $2.line); } } if ($$ == 0) { ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setFConst(0.0f); - $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), $2.line); + $$ = 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())); @@ -328,22 +298,22 @@ postfix_expression } | postfix_expression DOT FIELD_SELECTION { if ($1->isArray()) { - parseContext->error($3.line, "cannot apply dot operator to an array", ".", ""); - parseContext->recover(); + context->error($3.line, "cannot apply dot operator to an array", ".", ""); + context->recover(); } if ($1->isVector()) { TVectorFields fields; - if (! parseContext->parseVectorFields(*$3.string, $1->getNominalSize(), fields, $3.line)) { + if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, $3.line)) { fields.num = 1; fields.offsets[0] = 0; - parseContext->recover(); + context->recover(); } if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields - $$ = parseContext->addConstVectorNode(fields, $1, $3.line); + $$ = context->addConstVectorNode(fields, $1, $3.line); if ($$ == 0) { - parseContext->recover(); + context->recover(); $$ = $1; } else @@ -352,47 +322,47 @@ postfix_expression if (fields.num == 1) { ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setIConst(fields.offsets[0]); - TIntermTyped* index = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line); - $$ = parseContext->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line); + 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 = parseContext->intermediate.addSwizzle(fields, $3.line); - $$ = parseContext->intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line); + 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 (! parseContext->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) { + if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) { fields.wholeRow = false; fields.wholeCol = false; fields.row = 0; fields.col = 0; - parseContext->recover(); + context->recover(); } if (fields.wholeRow || fields.wholeCol) { - parseContext->error($2.line, " non-scalar fields not implemented yet", ".", ""); - parseContext->recover(); + context->error($2.line, " non-scalar fields not implemented yet", ".", ""); + context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setIConst(0); - TIntermTyped* index = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line); - $$ = parseContext->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line); + 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 = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line); - $$ = parseContext->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line); + 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) { - parseContext->error($2.line, "structure has no fields", "Internal Error", ""); - parseContext->recover(); + context->error($2.line, "structure has no fields", "Internal Error", ""); + context->recover(); $$ = $1; } else { unsigned int i; @@ -404,9 +374,9 @@ postfix_expression } if (fieldFound) { if ($1->getType().getQualifier() == EvqConst) { - $$ = parseContext->addConstStruct(*$3.string, $1, $2.line); + $$ = context->addConstStruct(*$3.string, $1, $2.line); if ($$ == 0) { - parseContext->recover(); + context->recover(); $$ = $1; } else { @@ -418,40 +388,40 @@ postfix_expression } else { ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setIConst(i); - TIntermTyped* index = parseContext->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, $3.line); - $$ = parseContext->intermediate.addIndex(EOpIndexDirectStruct, $1, index, $2.line); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, $3.line); + $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, $2.line); $$->setType(*(*fields)[i].type); } } else { - parseContext->error($2.line, " no such field in structure", $3.string->c_str(), ""); - parseContext->recover(); + context->error($2.line, " no such field in structure", $3.string->c_str(), ""); + context->recover(); $$ = $1; } } } else { - parseContext->error($2.line, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str(), ""); - parseContext->recover(); + 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 (parseContext->lValueErrorCheck($2.line, "++", $1)) - parseContext->recover(); - $$ = parseContext->intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line, parseContext->symbolTable); + if (context->lValueErrorCheck($2.line, "++", $1)) + context->recover(); + $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line, context->symbolTable); if ($$ == 0) { - parseContext->unaryOpError($2.line, "++", $1->getCompleteString()); - parseContext->recover(); + context->unaryOpError($2.line, "++", $1->getCompleteString()); + context->recover(); $$ = $1; } } | postfix_expression DEC_OP { - if (parseContext->lValueErrorCheck($2.line, "--", $1)) - parseContext->recover(); - $$ = parseContext->intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line, parseContext->symbolTable); + if (context->lValueErrorCheck($2.line, "--", $1)) + context->recover(); + $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line, context->symbolTable); if ($$ == 0) { - parseContext->unaryOpError($2.line, "--", $1->getCompleteString()); - parseContext->recover(); + context->unaryOpError($2.line, "--", $1->getCompleteString()); + context->recover(); $$ = $1; } } @@ -459,8 +429,8 @@ postfix_expression integer_expression : expression { - if (parseContext->integerErrorCheck($1, "[]")) - parseContext->recover(); + if (context->integerErrorCheck($1, "[]")) + context->recover(); $$ = $1; } ; @@ -478,18 +448,18 @@ function_call // Their parameters will be verified algorithmically. // TType type(EbtVoid, EbpUndefined); // use this to get the type back - if (parseContext->constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) { + if (context->constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) { $$ = 0; } else { // // It's a constructor, of type 'type'. // - $$ = parseContext->addConstructor($1.intermNode, &type, op, fnCall, $1.line); + $$ = context->addConstructor($1.intermNode, &type, op, fnCall, $1.line); } if ($$ == 0) { - parseContext->recover(); - $$ = parseContext->intermediate.setAggregateOperator(0, op, $1.line); + context->recover(); + $$ = context->intermediate.setAggregateOperator(0, op, $1.line); } $$->setType(type); } else { @@ -498,12 +468,15 @@ function_call // const TFunction* fnCandidate; bool builtIn; - fnCandidate = parseContext->findFunction($1.line, fnCall, &builtIn); + fnCandidate = context->findFunction($1.line, fnCall, &builtIn); if (fnCandidate) { // - // A declared function. But, it might still map to a built-in - // operation. + // A declared function. // + if (builtIn && !fnCandidate->getExtension().empty() && + context->extensionErrorCheck($1.line, fnCandidate->getExtension())) { + context->recover(); + } op = fnCandidate->getBuiltInOp(); if (builtIn && op != EOpNull) { // @@ -513,20 +486,20 @@ function_call // // Treat it like a built-in unary operator. // - $$ = parseContext->intermediate.addUnaryMath(op, $1.intermNode, 0, parseContext->symbolTable); + $$ = context->intermediate.addUnaryMath(op, $1.intermNode, 0, context->symbolTable); if ($$ == 0) { - parseContext->error($1.intermNode->getLine(), " wrong operand type", "Internal Error", + context->error($1.intermNode->getLine(), " wrong operand type", "Internal Error", "built in unary operator function. Type: %s", static_cast($1.intermNode)->getCompleteString().c_str()); YYERROR; } } else { - $$ = parseContext->intermediate.setAggregateOperator($1.intermAggregate, op, $1.line); + $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, $1.line); } } else { // This is a real function call - $$ = parseContext->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, $1.line); + $$ = 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 @@ -537,16 +510,14 @@ function_call $$->getAsAggregate()->setName(fnCandidate->getMangledName()); TQualifier qual; - TQualifierList& qualifierList = $$->getAsAggregate()->getQualifier(); for (int i = 0; i < fnCandidate->getParamCount(); ++i) { - qual = (*fnCandidate)[i].type->getQualifier(); + qual = fnCandidate->getParam(i).type->getQualifier(); if (qual == EvqOut || qual == EvqInOut) { - if (parseContext->lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) { - parseContext->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", ""); - parseContext->recover(); + 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(); } } - qualifierList.push_back(qual); } } $$->setType(fnCandidate->getReturnType()); @@ -555,8 +526,8 @@ function_call // Put on a dummy node for error recovery ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setFConst(0.0f); - $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line); - parseContext->recover(); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line); + context->recover(); } } delete fnCall; @@ -568,8 +539,8 @@ function_call_or_method $$ = $1; } | postfix_expression DOT function_call_generic { - parseContext->error($3.line, "methods are not supported", "", ""); - parseContext->recover(); + context->error($3.line, "methods are not supported", "", ""); + context->recover(); $$ = $3; } ; @@ -607,7 +578,7 @@ function_call_header_with_parameters TParameter param = { 0, new TType($3->getType()) }; $1.function->addParameter(param); $$.function = $1.function; - $$.intermNode = parseContext->intermediate.growAggregate($1.intermNode, $3, $2.line); + $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, $2.line); } ; @@ -625,19 +596,16 @@ function_identifier // Constructor // if ($1.array) { - if (parseContext->extensionErrorCheck($1.line, "GL_3DL_array_objects")) { - parseContext->recover(); - $1.setArray(false); - } + // Constructors for arrays are not allowed. + context->error($1.line, "cannot construct this type", "array", ""); + context->recover(); + $1.setArray(false); } + TOperator op = EOpNull; if ($1.userDef) { - TString tempString = ""; - TType type($1); - TFunction *function = new TFunction(&tempString, type, EOpConstructStruct); - $$ = function; + op = EOpConstructStruct; } else { - TOperator op = EOpNull; switch ($1.type) { case EbtFloat: if ($1.matrix) { @@ -671,29 +639,30 @@ function_identifier case 4: FRAG_VERT_ONLY("bvec4", $1.line); op = EOpConstructBVec4; break; } break; + default: break; } if (op == EOpNull) { - parseContext->error($1.line, "cannot construct this type", getBasicString($1.type), ""); - parseContext->recover(); + 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; } + TString tempString; + TType type($1); + TFunction *function = new TFunction(&tempString, type, op); + $$ = function; } | IDENTIFIER { - if (parseContext->reservedErrorCheck($1.line, *$1.string)) - parseContext->recover(); + if (context->reservedErrorCheck($1.line, *$1.string)) + context->recover(); TType type(EbtVoid, EbpUndefined); TFunction *function = new TFunction($1.string, type); $$ = function; } | FIELD_SELECTION { - if (parseContext->reservedErrorCheck($1.line, *$1.string)) - parseContext->recover(); + if (context->reservedErrorCheck($1.line, *$1.string)) + context->recover(); TType type(EbtVoid, EbpUndefined); TFunction *function = new TFunction($1.string, type); $$ = function; @@ -705,28 +674,28 @@ unary_expression $$ = $1; } | INC_OP unary_expression { - if (parseContext->lValueErrorCheck($1.line, "++", $2)) - parseContext->recover(); - $$ = parseContext->intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line, parseContext->symbolTable); + if (context->lValueErrorCheck($1.line, "++", $2)) + context->recover(); + $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line, context->symbolTable); if ($$ == 0) { - parseContext->unaryOpError($1.line, "++", $2->getCompleteString()); - parseContext->recover(); + context->unaryOpError($1.line, "++", $2->getCompleteString()); + context->recover(); $$ = $2; } } | DEC_OP unary_expression { - if (parseContext->lValueErrorCheck($1.line, "--", $2)) - parseContext->recover(); - $$ = parseContext->intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line, parseContext->symbolTable); + if (context->lValueErrorCheck($1.line, "--", $2)) + context->recover(); + $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line, context->symbolTable); if ($$ == 0) { - parseContext->unaryOpError($1.line, "--", $2->getCompleteString()); - parseContext->recover(); + context->unaryOpError($1.line, "--", $2->getCompleteString()); + context->recover(); $$ = $2; } } | unary_operator unary_expression { if ($1.op != EOpNull) { - $$ = parseContext->intermediate.addUnaryMath($1.op, $2, $1.line, parseContext->symbolTable); + $$ = context->intermediate.addUnaryMath($1.op, $2, $1.line, context->symbolTable); if ($$ == 0) { const char* errorOp = ""; switch($1.op) { @@ -734,8 +703,8 @@ unary_expression case EOpLogicalNot: errorOp = "!"; break; default: break; } - parseContext->unaryOpError($1.line, errorOp, $2->getCompleteString()); - parseContext->recover(); + context->unaryOpError($1.line, errorOp, $2->getCompleteString()); + context->recover(); $$ = $2; } } else @@ -755,19 +724,19 @@ multiplicative_expression : unary_expression { $$ = $1; } | multiplicative_expression STAR unary_expression { FRAG_VERT_ONLY("*", $2.line); - $$ = parseContext->intermediate.addBinaryMath(EOpMul, $1, $3, $2.line, parseContext->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, $2.line, context->symbolTable); if ($$ == 0) { - parseContext->binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString()); - parseContext->recover(); + context->binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); $$ = $1; } } | multiplicative_expression SLASH unary_expression { FRAG_VERT_ONLY("/", $2.line); - $$ = parseContext->intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, parseContext->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, context->symbolTable); if ($$ == 0) { - parseContext->binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString()); - parseContext->recover(); + context->binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); $$ = $1; } } @@ -776,18 +745,18 @@ multiplicative_expression additive_expression : multiplicative_expression { $$ = $1; } | additive_expression PLUS multiplicative_expression { - $$ = parseContext->intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, parseContext->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, context->symbolTable); if ($$ == 0) { - parseContext->binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString()); - parseContext->recover(); + context->binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); $$ = $1; } } | additive_expression DASH multiplicative_expression { - $$ = parseContext->intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, parseContext->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, context->symbolTable); if ($$ == 0) { - parseContext->binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString()); - parseContext->recover(); + context->binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); $$ = $1; } } @@ -800,43 +769,43 @@ shift_expression relational_expression : shift_expression { $$ = $1; } | relational_expression LEFT_ANGLE shift_expression { - $$ = parseContext->intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line, parseContext->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line, context->symbolTable); if ($$ == 0) { - parseContext->binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString()); - parseContext->recover(); + context->binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); } } | relational_expression RIGHT_ANGLE shift_expression { - $$ = parseContext->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, parseContext->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, context->symbolTable); if ($$ == 0) { - parseContext->binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString()); - parseContext->recover(); + context->binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); } } | relational_expression LE_OP shift_expression { - $$ = parseContext->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, parseContext->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, context->symbolTable); if ($$ == 0) { - parseContext->binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString()); - parseContext->recover(); + context->binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); } } | relational_expression GE_OP shift_expression { - $$ = parseContext->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, parseContext->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, context->symbolTable); if ($$ == 0) { - parseContext->binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString()); - parseContext->recover(); + context->binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); } } ; @@ -844,26 +813,24 @@ relational_expression equality_expression : relational_expression { $$ = $1; } | equality_expression EQ_OP relational_expression { - $$ = parseContext->intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, parseContext->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, context->symbolTable); if ($$ == 0) { - parseContext->binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString()); - parseContext->recover(); + context->binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); - } else if (($1->isArray() || $3->isArray()) && parseContext->extensionErrorCheck($2.line, "GL_3DL_array_objects")) - parseContext->recover(); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + } } | equality_expression NE_OP relational_expression { - $$ = parseContext->intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, parseContext->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, context->symbolTable); if ($$ == 0) { - parseContext->binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString()); - parseContext->recover(); + context->binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); - } else if (($1->isArray() || $3->isArray()) && parseContext->extensionErrorCheck($2.line, "GL_3DL_array_objects")) - parseContext->recover(); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + } } ; @@ -882,13 +849,13 @@ inclusive_or_expression logical_and_expression : inclusive_or_expression { $$ = $1; } | logical_and_expression AND_OP inclusive_or_expression { - $$ = parseContext->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line, parseContext->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line, context->symbolTable); if ($$ == 0) { - parseContext->binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString()); - parseContext->recover(); + context->binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); } } ; @@ -896,13 +863,13 @@ logical_and_expression logical_xor_expression : logical_and_expression { $$ = $1; } | logical_xor_expression XOR_OP logical_and_expression { - $$ = parseContext->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line, parseContext->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line, context->symbolTable); if ($$ == 0) { - parseContext->binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString()); - parseContext->recover(); + context->binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); } } ; @@ -910,13 +877,13 @@ logical_xor_expression logical_or_expression : logical_xor_expression { $$ = $1; } | logical_or_expression OR_OP logical_xor_expression { - $$ = parseContext->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line, parseContext->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line, context->symbolTable); if ($$ == 0) { - parseContext->binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString()); - parseContext->recover(); + context->binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); } } ; @@ -924,16 +891,16 @@ logical_or_expression conditional_expression : logical_or_expression { $$ = $1; } | logical_or_expression QUESTION expression COLON assignment_expression { - if (parseContext->boolErrorCheck($2.line, $1)) - parseContext->recover(); + if (context->boolErrorCheck($2.line, $1)) + context->recover(); - $$ = parseContext->intermediate.addSelection($1, $3, $5, $2.line); + $$ = context->intermediate.addSelection($1, $3, $5, $2.line); if ($3->getType() != $5->getType()) $$ = 0; if ($$ == 0) { - parseContext->binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString()); - parseContext->recover(); + context->binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString()); + context->recover(); $$ = $5; } } @@ -942,15 +909,14 @@ conditional_expression assignment_expression : conditional_expression { $$ = $1; } | unary_expression assignment_operator assignment_expression { - if (parseContext->lValueErrorCheck($2.line, "assign", $1)) - parseContext->recover(); - $$ = parseContext->intermediate.addAssign($2.op, $1, $3, $2.line); + if (context->lValueErrorCheck($2.line, "assign", $1)) + context->recover(); + $$ = context->intermediate.addAssign($2.op, $1, $3, $2.line); if ($$ == 0) { - parseContext->assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString()); - parseContext->recover(); + context->assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); $$ = $1; - } else if (($1->isArray() || $3->isArray()) && parseContext->extensionErrorCheck($2.line, "GL_3DL_array_objects")) - parseContext->recover(); + } } ; @@ -967,10 +933,10 @@ expression $$ = $1; } | expression COMMA assignment_expression { - $$ = parseContext->intermediate.addComma($1, $3, $2.line); + $$ = context->intermediate.addComma($1, $3, $2.line); if ($$ == 0) { - parseContext->binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString()); - parseContext->recover(); + context->binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); $$ = $3; } } @@ -978,8 +944,8 @@ expression constant_expression : conditional_expression { - if (parseContext->constErrorCheck($1)) - parseContext->recover(); + if (context->constErrorCheck($1)) + context->recover(); $$ = $1; } ; @@ -994,16 +960,16 @@ declaration for (int i = 0; i < function.getParamCount(); i++) { - TParameter ¶m = function[i]; + const TParameter ¶m = function.getParam(i); if (param.name != 0) { TVariable *variable = new TVariable(param.name, *param.type); - prototype = parseContext->intermediate.growAggregate(prototype, parseContext->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), $1.line), $1.line); + prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), $1.line), $1.line); } else { - prototype = parseContext->intermediate.growAggregate(prototype, parseContext->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line); + prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line); } } @@ -1016,7 +982,7 @@ declaration $$ = $1.intermAggregate; } | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON { - parseContext->symbolTable.setDefaultPrecision( $3.type, $2 ); + context->symbolTable.setDefaultPrecision( $3.type, $2 ); $$ = 0; } ; @@ -1031,16 +997,16 @@ function_prototype // // Redeclarations are allowed. But, return types and parameter qualifiers must match. // - TFunction* prevDec = static_cast(parseContext->symbolTable.find($1->getMangledName())); + TFunction* prevDec = static_cast(context->symbolTable.find($1->getMangledName())); if (prevDec) { if (prevDec->getReturnType() != $1->getReturnType()) { - parseContext->error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString(), ""); - parseContext->recover(); + 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)[i].type->getQualifier() != (*$1)[i].type->getQualifier()) { - parseContext->error($2.line, "overloaded functions must have the same parameter qualifiers", (*$1)[i].type->getQualifierString(), ""); - parseContext->recover(); + if (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(); } } } @@ -1053,7 +1019,7 @@ function_prototype $$.function = $1; $$.line = $2.line; - parseContext->symbolTable.insert(*$$.function); + context->symbolTable.insert(*$$.function); } ; @@ -1085,8 +1051,8 @@ function_header_with_parameters // // This parameter > first is void // - parseContext->error($2.line, "cannot be an argument type except for '(void)'", "void", ""); - parseContext->recover(); + context->error($2.line, "cannot be an argument type except for '(void)'", "void", ""); + context->recover(); delete $3.param.type; } else { // Add the parameter @@ -1099,12 +1065,12 @@ function_header_with_parameters function_header : fully_specified_type IDENTIFIER LEFT_PAREN { if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) { - parseContext->error($2.line, "no qualifiers allowed for function return", getQualifierString($1.qualifier), ""); - parseContext->recover(); + 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 (parseContext->structQualifierErrorCheck($2.line, $1)) - parseContext->recover(); + if (context->structQualifierErrorCheck($2.line, $1)) + context->recover(); // Add the function as a prototype after parsing it (we do not support recursion) TFunction *function; @@ -1118,26 +1084,26 @@ parameter_declarator // Type + name : type_specifier IDENTIFIER { if ($1.type == EbtVoid) { - parseContext->error($2.line, "illegal use of type 'void'", $2.string->c_str(), ""); - parseContext->recover(); + context->error($2.line, "illegal use of type 'void'", $2.string->c_str(), ""); + context->recover(); } - if (parseContext->reservedErrorCheck($2.line, *$2.string)) - parseContext->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 (parseContext->arrayTypeErrorCheck($3.line, $1)) - parseContext->recover(); + if (context->arrayTypeErrorCheck($3.line, $1)) + context->recover(); - if (parseContext->reservedErrorCheck($2.line, *$2.string)) - parseContext->recover(); + if (context->reservedErrorCheck($2.line, *$2.string)) + context->recover(); int size; - if (parseContext->arraySizeErrorCheck($3.line, $4, size)) - parseContext->recover(); + if (context->arraySizeErrorCheck($3.line, $4, size)) + context->recover(); $1.setArray(true, size); TType* type = new TType($1); @@ -1158,30 +1124,30 @@ parameter_declaration // : type_qualifier parameter_qualifier parameter_declarator { $$ = $3; - if (parseContext->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type)) - parseContext->recover(); + if (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type)) + context->recover(); } | parameter_qualifier parameter_declarator { $$ = $2; - if (parseContext->parameterSamplerErrorCheck($2.line, $1, *$2.param.type)) - parseContext->recover(); - if (parseContext->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type)) - parseContext->recover(); + 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 (parseContext->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type)) - parseContext->recover(); + if (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type)) + context->recover(); } | parameter_qualifier parameter_type_specifier { $$ = $2; - if (parseContext->parameterSamplerErrorCheck($2.line, $1, *$2.param.type)) - parseContext->recover(); - if (parseContext->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type)) - parseContext->recover(); + if (context->parameterSamplerErrorCheck($2.line, $1, *$2.param.type)) + context->recover(); + if (context->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type)) + context->recover(); } ; @@ -1212,152 +1178,83 @@ init_declarator_list $$ = $1; if ($$.type.precision == EbpUndefined) { - $$.type.precision = parseContext->symbolTable.getDefaultPrecision($1.type.type); - if (parseContext->precisionErrorCheck($1.line, $$.type.precision, $1.type.type)) { - parseContext->recover(); + $$.type.precision = context->symbolTable.getDefaultPrecision($1.type.type); + if (context->precisionErrorCheck($1.line, $$.type.precision, $1.type.type)) { + context->recover(); } } } | init_declarator_list COMMA IDENTIFIER { - $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, parseContext->intermediate.addSymbol(0, *$3.string, TType($1.type), $3.line), $3.line); + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(0, *$3.string, TType($1.type), $3.line), $3.line); - if (parseContext->structQualifierErrorCheck($3.line, $$.type)) - parseContext->recover(); + if (context->structQualifierErrorCheck($3.line, $$.type)) + context->recover(); - if (parseContext->nonInitConstErrorCheck($3.line, *$3.string, $$.type)) - parseContext->recover(); + if (context->nonInitConstErrorCheck($3.line, *$3.string, $$.type)) + context->recover(); - if (parseContext->nonInitErrorCheck($3.line, *$3.string, $$.type)) - parseContext->recover(); + if (context->nonInitErrorCheck($3.line, *$3.string, $$.type)) + context->recover(); } | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET { - if (parseContext->structQualifierErrorCheck($3.line, $1.type)) - parseContext->recover(); + if (context->structQualifierErrorCheck($3.line, $1.type)) + context->recover(); - if (parseContext->nonInitConstErrorCheck($3.line, *$3.string, $1.type)) - parseContext->recover(); + if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type)) + context->recover(); $$ = $1; - if (parseContext->arrayTypeErrorCheck($4.line, $1.type) || parseContext->arrayQualifierErrorCheck($4.line, $1.type)) - parseContext->recover(); + if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type)) + context->recover(); else { $1.type.setArray(true); TVariable* variable; - if (parseContext->arrayErrorCheck($4.line, *$3.string, $1.type, variable)) - parseContext->recover(); + if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable)) + context->recover(); } } | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { - if (parseContext->structQualifierErrorCheck($3.line, $1.type)) - parseContext->recover(); + if (context->structQualifierErrorCheck($3.line, $1.type)) + context->recover(); - if (parseContext->nonInitConstErrorCheck($3.line, *$3.string, $1.type)) - parseContext->recover(); + if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type)) + context->recover(); $$ = $1; - if (parseContext->arrayTypeErrorCheck($4.line, $1.type) || parseContext->arrayQualifierErrorCheck($4.line, $1.type)) - parseContext->recover(); + if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type)) + context->recover(); else { int size; - if (parseContext->arraySizeErrorCheck($4.line, $5, size)) - parseContext->recover(); + if (context->arraySizeErrorCheck($4.line, $5, size)) + context->recover(); $1.type.setArray(true, size); TVariable* variable; - if (parseContext->arrayErrorCheck($4.line, *$3.string, $1.type, variable)) - parseContext->recover(); + if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable)) + context->recover(); TType type = TType($1.type); type.setArraySize(size); - $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, parseContext->intermediate.addSymbol(0, *$3.string, type, $3.line), $3.line); - } - } - | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET EQUAL initializer { - if (parseContext->structQualifierErrorCheck($3.line, $1.type)) - parseContext->recover(); - - $$ = $1; - - TVariable* variable = 0; - if (parseContext->arrayTypeErrorCheck($4.line, $1.type) || parseContext->arrayQualifierErrorCheck($4.line, $1.type)) - parseContext->recover(); - else { - $1.type.setArray(true, $7->getType().getArraySize()); - if (parseContext->arrayErrorCheck($4.line, *$3.string, $1.type, variable)) - parseContext->recover(); - } - - if (parseContext->extensionErrorCheck($$.line, "GL_3DL_array_objects")) - parseContext->recover(); - else { - TIntermNode* intermNode; - if (!parseContext->executeInitializer($3.line, *$3.string, $1.type, $7, intermNode, variable)) { - // - // build the intermediate representation - // - if (intermNode) - $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, intermNode, $6.line); - else - $$.intermAggregate = $1.intermAggregate; - } else { - parseContext->recover(); - $$.intermAggregate = 0; - } - } - } - | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer { - if (parseContext->structQualifierErrorCheck($3.line, $1.type)) - parseContext->recover(); - - $$ = $1; - - TVariable* variable = 0; - if (parseContext->arrayTypeErrorCheck($4.line, $1.type) || parseContext->arrayQualifierErrorCheck($4.line, $1.type)) - parseContext->recover(); - else { - int size; - if (parseContext->arraySizeErrorCheck($4.line, $5, size)) - parseContext->recover(); - $1.type.setArray(true, size); - if (parseContext->arrayErrorCheck($4.line, *$3.string, $1.type, variable)) - parseContext->recover(); - } - - if (parseContext->extensionErrorCheck($$.line, "GL_3DL_array_objects")) - parseContext->recover(); - else { - TIntermNode* intermNode; - if (!parseContext->executeInitializer($3.line, *$3.string, $1.type, $8, intermNode, variable)) { - // - // build the intermediate representation - // - if (intermNode) - $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, intermNode, $7.line); - else - $$.intermAggregate = $1.intermAggregate; - } else { - parseContext->recover(); - $$.intermAggregate = 0; - } + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(0, *$3.string, type, $3.line), $3.line); } } | init_declarator_list COMMA IDENTIFIER EQUAL initializer { - if (parseContext->structQualifierErrorCheck($3.line, $1.type)) - parseContext->recover(); + if (context->structQualifierErrorCheck($3.line, $1.type)) + context->recover(); $$ = $1; TIntermNode* intermNode; - if (!parseContext->executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) { + if (!context->executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) { // // build the intermediate representation // if (intermNode) - $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, intermNode, $4.line); + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, $4.line); else $$.intermAggregate = $1.intermAggregate; } else { - parseContext->recover(); + context->recover(); $$.intermAggregate = 0; } } @@ -1366,88 +1263,88 @@ init_declarator_list single_declaration : fully_specified_type { $$.type = $1; - $$.intermAggregate = parseContext->intermediate.makeAggregate(parseContext->intermediate.addSymbol(0, "", TType($1), $1.line), $1.line); + $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), $1.line), $1.line); } | fully_specified_type IDENTIFIER { - $$.intermAggregate = parseContext->intermediate.makeAggregate(parseContext->intermediate.addSymbol(0, *$2.string, TType($1), $2.line), $2.line); + $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line), $2.line); - if (parseContext->structQualifierErrorCheck($2.line, $$.type)) - parseContext->recover(); + if (context->structQualifierErrorCheck($2.line, $$.type)) + context->recover(); - if (parseContext->nonInitConstErrorCheck($2.line, *$2.string, $$.type)) - parseContext->recover(); + if (context->nonInitConstErrorCheck($2.line, *$2.string, $$.type)) + context->recover(); $$.type = $1; - if (parseContext->nonInitErrorCheck($2.line, *$2.string, $$.type)) - parseContext->recover(); + if (context->nonInitErrorCheck($2.line, *$2.string, $$.type)) + context->recover(); } | fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET { - $$.intermAggregate = parseContext->intermediate.makeAggregate(parseContext->intermediate.addSymbol(0, *$2.string, TType($1), $2.line), $2.line); + $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line), $2.line); - if (parseContext->structQualifierErrorCheck($2.line, $1)) - parseContext->recover(); + if (context->structQualifierErrorCheck($2.line, $1)) + context->recover(); - if (parseContext->nonInitConstErrorCheck($2.line, *$2.string, $1)) - parseContext->recover(); + if (context->nonInitConstErrorCheck($2.line, *$2.string, $1)) + context->recover(); $$.type = $1; - if (parseContext->arrayTypeErrorCheck($3.line, $1) || parseContext->arrayQualifierErrorCheck($3.line, $1)) - parseContext->recover(); + if (context->arrayTypeErrorCheck($3.line, $1) || context->arrayQualifierErrorCheck($3.line, $1)) + context->recover(); else { $1.setArray(true); TVariable* variable; - if (parseContext->arrayErrorCheck($3.line, *$2.string, $1, variable)) - parseContext->recover(); + if (context->arrayErrorCheck($3.line, *$2.string, $1, variable)) + context->recover(); } } | fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { TType type = TType($1); int size; - if (parseContext->arraySizeErrorCheck($2.line, $4, size)) - parseContext->recover(); + if (context->arraySizeErrorCheck($2.line, $4, size)) + context->recover(); type.setArraySize(size); - $$.intermAggregate = parseContext->intermediate.makeAggregate(parseContext->intermediate.addSymbol(0, *$2.string, type, $2.line), $2.line); + $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, *$2.string, type, $2.line), $2.line); - if (parseContext->structQualifierErrorCheck($2.line, $1)) - parseContext->recover(); + if (context->structQualifierErrorCheck($2.line, $1)) + context->recover(); - if (parseContext->nonInitConstErrorCheck($2.line, *$2.string, $1)) - parseContext->recover(); + if (context->nonInitConstErrorCheck($2.line, *$2.string, $1)) + context->recover(); $$.type = $1; - if (parseContext->arrayTypeErrorCheck($3.line, $1) || parseContext->arrayQualifierErrorCheck($3.line, $1)) - parseContext->recover(); + if (context->arrayTypeErrorCheck($3.line, $1) || context->arrayQualifierErrorCheck($3.line, $1)) + context->recover(); else { int size; - if (parseContext->arraySizeErrorCheck($3.line, $4, size)) - parseContext->recover(); + if (context->arraySizeErrorCheck($3.line, $4, size)) + context->recover(); $1.setArray(true, size); TVariable* variable; - if (parseContext->arrayErrorCheck($3.line, *$2.string, $1, variable)) - parseContext->recover(); + if (context->arrayErrorCheck($3.line, *$2.string, $1, variable)) + context->recover(); } } | fully_specified_type IDENTIFIER EQUAL initializer { - if (parseContext->structQualifierErrorCheck($2.line, $1)) - parseContext->recover(); + if (context->structQualifierErrorCheck($2.line, $1)) + context->recover(); $$.type = $1; TIntermNode* intermNode; - if (!parseContext->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) { + if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) { // // Build intermediate representation // if(intermNode) - $$.intermAggregate = parseContext->intermediate.makeAggregate(intermNode, $3.line); + $$.intermAggregate = context->intermediate.makeAggregate(intermNode, $3.line); else $$.intermAggregate = 0; } else { - parseContext->recover(); + context->recover(); $$.intermAggregate = 0; } } @@ -1479,14 +1376,14 @@ single_declaration // //input_or_output // : INPUT { -// if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "input")) -// parseContext->recover(); +// if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "input")) +// context->recover(); // UNPACK_ONLY("input", $1.line); // $$.qualifier = EvqInput; // } // | OUTPUT { -// if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "output")) -// parseContext->recover(); +// if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "output")) +// context->recover(); // PACK_ONLY("output", $1.line); // $$.qualifier = EvqOutput; // } @@ -1515,12 +1412,12 @@ single_declaration // //buffer_declaration // : type_specifier IDENTIFIER COLON constant_expression SEMICOLON { -// if (parseContext->reservedErrorCheck($2.line, *$2.string, parseContext)) -// parseContext->recover(); +// if (context->reservedErrorCheck($2.line, *$2.string, context)) +// context->recover(); // $$.variable = new TVariable($2.string, $1); -// if (! parseContext->symbolTable.insert(*$$.variable)) { -// parseContext->error($2.line, "redefinition", $$.variable->getName().c_str(), ""); -// parseContext->recover(); +// 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 // } // } @@ -1531,31 +1428,27 @@ fully_specified_type $$ = $1; if ($1.array) { - if (parseContext->extensionErrorCheck($1.line, "GL_3DL_array_objects")) { - parseContext->recover(); - $1.setArray(false); - } + context->error($1.line, "not supported", "first-class array", ""); + context->recover(); + $1.setArray(false); } } | type_qualifier type_specifier { - if ($2.array && parseContext->extensionErrorCheck($2.line, "GL_3DL_array_objects")) { - parseContext->recover(); - $2.setArray(false); - } - if ($2.array && parseContext->arrayQualifierErrorCheck($2.line, $1)) { - parseContext->recover(); + 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)) { - parseContext->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), ""); - parseContext->recover(); + 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)) { - parseContext->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), ""); - parseContext->recover(); + context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), ""); + context->recover(); } $$ = $2; $$.qualifier = $1.qualifier; @@ -1568,29 +1461,29 @@ type_qualifier } | ATTRIBUTE { VERTEX_ONLY("attribute", $1.line); - if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "attribute")) - parseContext->recover(); + if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "attribute")) + context->recover(); $$.setBasic(EbtVoid, EvqAttribute, $1.line); } | VARYING { - if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "varying")) - parseContext->recover(); - if (parseContext->language == EShLangVertex) + 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 (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "invariant varying")) - parseContext->recover(); - if (parseContext->language == EShLangVertex) + 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 (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "uniform")) - parseContext->recover(); + if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "uniform")) + context->recover(); $$.setBasic(EbtVoid, EvqUniform, $1.line); } ; @@ -1624,12 +1517,12 @@ type_specifier_no_prec | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET { $$ = $1; - if (parseContext->arrayTypeErrorCheck($2.line, $1)) - parseContext->recover(); + if (context->arrayTypeErrorCheck($2.line, $1)) + context->recover(); else { int size; - if (parseContext->arraySizeErrorCheck($2.line, $3, size)) - parseContext->recover(); + if (context->arraySizeErrorCheck($2.line, $3, size)) + context->recover(); $$.setArray(true, size); } } @@ -1637,103 +1530,103 @@ type_specifier_no_prec type_specifier_nonarray : VOID_TYPE { - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtVoid, qual, $1.line); } | FLOAT_TYPE { - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtFloat, qual, $1.line); } | INT_TYPE { - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtInt, qual, $1.line); } | BOOL_TYPE { - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtBool, qual, $1.line); } // | UNSIGNED INT_TYPE { // PACK_UNPACK_ONLY("unsigned", $1.line); -// TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; +// TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; // $$.setBasic(EbtInt, qual, $1.line); // } | VEC2 { - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtFloat, qual, $1.line); $$.setAggregate(2); } | VEC3 { - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtFloat, qual, $1.line); $$.setAggregate(3); } | VEC4 { - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtFloat, qual, $1.line); $$.setAggregate(4); } | BVEC2 { - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtBool, qual, $1.line); $$.setAggregate(2); } | BVEC3 { - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtBool, qual, $1.line); $$.setAggregate(3); } | BVEC4 { - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtBool, qual, $1.line); $$.setAggregate(4); } | IVEC2 { - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtInt, qual, $1.line); $$.setAggregate(2); } | IVEC3 { - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtInt, qual, $1.line); $$.setAggregate(3); } | IVEC4 { - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtInt, qual, $1.line); $$.setAggregate(4); } | MATRIX2 { FRAG_VERT_ONLY("mat2", $1.line); - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtFloat, qual, $1.line); $$.setAggregate(2, true); } | MATRIX3 { FRAG_VERT_ONLY("mat3", $1.line); - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtFloat, qual, $1.line); $$.setAggregate(3, true); } | MATRIX4 { FRAG_VERT_ONLY("mat4", $1.line); - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtFloat, qual, $1.line); $$.setAggregate(4, true); } | SAMPLER2D { FRAG_VERT_ONLY("sampler2D", $1.line); - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtSampler2D, qual, $1.line); } | SAMPLERCUBE { FRAG_VERT_ONLY("samplerCube", $1.line); - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtSamplerCube, qual, $1.line); } | struct_specifier { FRAG_VERT_ONLY("struct", $1.line); $$ = $1; - $$.qualifier = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; } | TYPE_NAME { // @@ -1741,7 +1634,7 @@ type_specifier_nonarray // type. // TType& structure = static_cast($1.symbol)->getType(); - TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtStruct, qual, $1.line); $$.userDef = &structure; } @@ -1749,14 +1642,14 @@ type_specifier_nonarray struct_specifier : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE { - if (parseContext->reservedErrorCheck($2.line, *$2.string)) - parseContext->recover(); + 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 (! parseContext->symbolTable.insert(*userTypeDef)) { - parseContext->error($2.line, "redefinition", $2.string->c_str(), "struct"); - parseContext->recover(); + if (! context->symbolTable.insert(*userTypeDef)) { + context->error($2.line, "redefinition", $2.string->c_str(), "struct"); + context->recover(); } $$.setBasic(EbtStruct, EvqTemporary, $1.line); $$.userDef = structure; @@ -1777,8 +1670,8 @@ struct_declaration_list for (unsigned int i = 0; i < $2->size(); ++i) { for (unsigned int j = 0; j < $$->size(); ++j) { if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) { - parseContext->error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str()); - parseContext->recover(); + context->error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str()); + context->recover(); } } $$->push_back((*$2)[i]); @@ -1790,8 +1683,8 @@ struct_declaration : type_specifier struct_declarator_list SEMICOLON { $$ = $2; - if (parseContext->voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) { - parseContext->recover(); + if (context->voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) { + context->recover(); } for (unsigned int i = 0; i < $$->size(); ++i) { // @@ -1804,8 +1697,8 @@ struct_declaration // don't allow arrays of arrays if (type->isArray()) { - if (parseContext->arrayTypeErrorCheck($1.line, $1)) - parseContext->recover(); + if (context->arrayTypeErrorCheck($1.line, $1)) + context->recover(); } if ($1.array) type->setArraySize($1.arraySize); @@ -1829,24 +1722,24 @@ struct_declarator_list struct_declarator : IDENTIFIER { - if (parseContext->reservedErrorCheck($1.line, *$1.string)) - parseContext->recover(); + 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 (parseContext->reservedErrorCheck($1.line, *$1.string)) - parseContext->recover(); + if (context->reservedErrorCheck($1.line, *$1.string)) + context->recover(); $$.type = new TType(EbtVoid, EbpUndefined); $$.line = $1.line; $$.type->setFieldName(*$1.string); int size; - if (parseContext->arraySizeErrorCheck($2.line, $3, size)) - parseContext->recover(); + if (context->arraySizeErrorCheck($2.line, $3, size)) + context->recover(); $$.type->setArraySize(size); } ; @@ -1876,7 +1769,7 @@ simple_statement compound_statement : LEFT_BRACE RIGHT_BRACE { $$ = 0; } - | LEFT_BRACE { parseContext->symbolTable.push(); } statement_list { parseContext->symbolTable.pop(); } RIGHT_BRACE { + | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE { if ($3 != 0) $3->setOp(EOpSequence); $$ = $3; @@ -1902,10 +1795,10 @@ compound_statement_no_new_scope statement_list : statement { - $$ = parseContext->intermediate.makeAggregate($1, 0); + $$ = context->intermediate.makeAggregate($1, 0); } | statement_list statement { - $$ = parseContext->intermediate.growAggregate($1, $2, 0); + $$ = context->intermediate.growAggregate($1, $2, 0); } ; @@ -1916,9 +1809,9 @@ expression_statement selection_statement : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement { - if (parseContext->boolErrorCheck($1.line, $3)) - parseContext->recover(); - $$ = parseContext->intermediate.addSelection($3, $5, $1.line); + if (context->boolErrorCheck($1.line, $3)) + context->recover(); + $$ = context->intermediate.addSelection($3, $5, $1.line); } ; @@ -1939,42 +1832,42 @@ condition // In 1996 c++ draft, conditions can include single declarations : expression { $$ = $1; - if (parseContext->boolErrorCheck($1->getLine(), $1)) - parseContext->recover(); + if (context->boolErrorCheck($1->getLine(), $1)) + context->recover(); } | fully_specified_type IDENTIFIER EQUAL initializer { TIntermNode* intermNode; - if (parseContext->structQualifierErrorCheck($2.line, $1)) - parseContext->recover(); - if (parseContext->boolErrorCheck($2.line, $1)) - parseContext->recover(); + if (context->structQualifierErrorCheck($2.line, $1)) + context->recover(); + if (context->boolErrorCheck($2.line, $1)) + context->recover(); - if (!parseContext->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) + if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) $$ = $4; else { - parseContext->recover(); + context->recover(); $$ = 0; } } ; iteration_statement - : WHILE LEFT_PAREN { parseContext->symbolTable.push(); ++parseContext->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope { - parseContext->symbolTable.pop(); - $$ = parseContext->intermediate.addLoop(0, $6, $4, 0, true, $1.line); - --parseContext->loopNestingLevel; + : 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 { ++parseContext->loopNestingLevel; } statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { - if (parseContext->boolErrorCheck($8.line, $6)) - parseContext->recover(); + | DO { ++context->loopNestingLevel; } statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { + if (context->boolErrorCheck($8.line, $6)) + context->recover(); - $$ = parseContext->intermediate.addLoop(0, $3, $6, 0, false, $4.line); - --parseContext->loopNestingLevel; + $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, $4.line); + --context->loopNestingLevel; } - | FOR LEFT_PAREN { parseContext->symbolTable.push(); ++parseContext->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { - parseContext->symbolTable.pop(); - $$ = parseContext->intermediate.addLoop($4, $7, reinterpret_cast($5.node1), reinterpret_cast($5.node2), true, $1.line); - --parseContext->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($5.node1), reinterpret_cast($5.node2), $7, $1.line); + --context->loopNestingLevel; } ; @@ -2009,40 +1902,40 @@ for_rest_statement jump_statement : CONTINUE SEMICOLON { - if (parseContext->loopNestingLevel <= 0) { - parseContext->error($1.line, "continue statement only allowed in loops", "", ""); - parseContext->recover(); + if (context->loopNestingLevel <= 0) { + context->error($1.line, "continue statement only allowed in loops", "", ""); + context->recover(); } - $$ = parseContext->intermediate.addBranch(EOpContinue, $1.line); + $$ = context->intermediate.addBranch(EOpContinue, $1.line); } | BREAK SEMICOLON { - if (parseContext->loopNestingLevel <= 0) { - parseContext->error($1.line, "break statement only allowed in loops", "", ""); - parseContext->recover(); + if (context->loopNestingLevel <= 0) { + context->error($1.line, "break statement only allowed in loops", "", ""); + context->recover(); } - $$ = parseContext->intermediate.addBranch(EOpBreak, $1.line); + $$ = context->intermediate.addBranch(EOpBreak, $1.line); } | RETURN SEMICOLON { - $$ = parseContext->intermediate.addBranch(EOpReturn, $1.line); - if (parseContext->currentFunctionType->getBasicType() != EbtVoid) { - parseContext->error($1.line, "non-void function must return a value", "return", ""); - parseContext->recover(); + $$ = 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 { - $$ = parseContext->intermediate.addBranch(EOpReturn, $2, $1.line); - parseContext->functionReturnsValue = true; - if (parseContext->currentFunctionType->getBasicType() == EbtVoid) { - parseContext->error($1.line, "void function cannot return a value", "return", ""); - parseContext->recover(); - } else if (*(parseContext->currentFunctionType) != $2->getType()) { - parseContext->error($1.line, "function return is not matching type:", "return", ""); - parseContext->recover(); + $$ = 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); - $$ = parseContext->intermediate.addBranch(EOpKill, $1.line); + $$ = context->intermediate.addBranch(EOpKill, $1.line); } ; @@ -2051,11 +1944,11 @@ jump_statement translation_unit : external_declaration { $$ = $1; - parseContext->treeRoot = $$; + context->treeRoot = $$; } | translation_unit external_declaration { - $$ = parseContext->intermediate.growAggregate($1, $2, 0); - parseContext->treeRoot = $$; + $$ = context->intermediate.growAggregate($1, $2, 0); + context->treeRoot = $$; } ; @@ -2070,8 +1963,8 @@ external_declaration function_definition : function_prototype { - TFunction& function = *($1.function); - TFunction* prevDec = static_cast(parseContext->symbolTable.find(function.getMangledName())); + TFunction* function = $1.function; + TFunction* prevDec = static_cast(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 @@ -2081,35 +1974,35 @@ function_definition // // Then this function already has a body. // - parseContext->error($1.line, "function already has a body", function.getName().c_str(), ""); - parseContext->recover(); + 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) { - parseContext->error($1.line, "function cannot take any parameter(s)", function.getName().c_str(), ""); - parseContext->recover(); + 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) { - parseContext->error($1.line, "", function.getReturnType().getBasicString(), "main function cannot return a value"); - parseContext->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 // - parseContext->symbolTable.push(); + context->symbolTable.push(); // // Remember the return type for later checking for RETURN statements. // - parseContext->currentFunctionType = &(prevDec->getReturnType()); - parseContext->functionReturnsValue = false; + context->currentFunctionType = &(prevDec->getReturnType()); + context->functionReturnsValue = false; // // Insert parameters into the symbol table. @@ -2120,59 +2013,60 @@ function_definition // knows where to find parameters. // TIntermAggregate* paramNodes = new TIntermAggregate; - for (int i = 0; i < function.getParamCount(); i++) { - TParameter& param = function[i]; + 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 (! parseContext->symbolTable.insert(*variable)) { - parseContext->error($1.line, "redefinition", variable->getName().c_str(), ""); - parseContext->recover(); + if (! context->symbolTable.insert(*variable)) { + context->error($1.line, "redefinition", variable->getName().c_str(), ""); + context->recover(); delete variable; } - // - // Transfer ownership of name pointer to symbol table. - // - param.name = 0; // // Add the parameter to the HIL // - paramNodes = parseContext->intermediate.growAggregate( + paramNodes = context->intermediate.growAggregate( paramNodes, - parseContext->intermediate.addSymbol(variable->getUniqueId(), + context->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), $1.line), $1.line); } else { - paramNodes = parseContext->intermediate.growAggregate(paramNodes, parseContext->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line); + paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line); } } - parseContext->intermediate.setAggregateOperator(paramNodes, EOpParameters, $1.line); + context->intermediate.setAggregateOperator(paramNodes, EOpParameters, $1.line); $1.intermAggregate = paramNodes; - parseContext->loopNestingLevel = 0; + 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 (parseContext->currentFunctionType->getBasicType() != EbtVoid && ! parseContext->functionReturnsValue) { - parseContext->error($1.line, "function does not return a value:", "", $1.function->getName().c_str()); - parseContext->recover(); + if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) { + context->error($1.line, "function does not return a value:", "", $1.function->getName().c_str()); + context->recover(); } - parseContext->symbolTable.pop(); - $$ = parseContext->intermediate.growAggregate($1.intermAggregate, $3, 0); - parseContext->intermediate.setAggregateOperator($$, EOpFunction, $1.line); + 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(parseContext->contextPragma.optimize); - $$->getAsAggregate()->setDebug(parseContext->contextPragma.debug); - $$->getAsAggregate()->addToPragmaTable(parseContext->contextPragma.pragmaTable); + $$->getAsAggregate()->setOptimize(context->contextPragma.optimize); + $$->getAsAggregate()->setDebug(context->contextPragma.debug); + $$->getAsAggregate()->addToPragmaTable(context->contextPragma.pragmaTable); } ; %% + +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 0000000..9d5f53f --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/glslang_lex.cpp @@ -0,0 +1,3186 @@ +#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 +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . 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 +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 ); + +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 fwrite( yytext, yyleng, 1, yyout ) +#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 = '*'; \ + int 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(atof_dot(yytext)); return(FLOATCONSTANT); } + YY_BREAK +case 94: +YY_RULE_SETUP +{ yylval->lex.f = static_cast(atof_dot(yytext)); return(FLOATCONSTANT); } + YY_BREAK +case 95: +YY_RULE_SETUP +{ yylval->lex.f = static_cast(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:: 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(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 0000000..d00c7a3 --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/compiler/glslang_tab.cpp @@ -0,0 +1,4710 @@ +/* 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 187 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 /* 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 YYENABLE_NLS +# if ENABLE_NLS +# include /* 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 /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* 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 /* 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 /* 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 1334 + +/* 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, 137, -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, 656, 663, 673, 676, + 686, 696, 717, 718, 719, 724, 725, 734, 746, 747, + 755, 766, 770, 771, 781, 791, 801, 814, 815, 825, + 838, 842, 846, 850, 851, 864, 865, 878, 879, 892, + 893, 910, 911, 924, 925, 926, 927, 928, 932, 935, + 946, 954, 979, 984, 991, 1027, 1030, 1037, 1045, 1066, + 1085, 1096, 1125, 1130, 1140, 1145, 1155, 1158, 1161, 1164, + 1170, 1177, 1187, 1199, 1217, 1241, 1264, 1268, 1282, 1302, + 1331, 1351, 1427, 1436, 1459, 1462, 1468, 1476, 1484, 1492, + 1495, 1502, 1505, 1508, 1514, 1517, 1532, 1536, 1540, 1544, + 1553, 1558, 1563, 1568, 1573, 1578, 1583, 1588, 1593, 1598, + 1604, 1610, 1616, 1621, 1626, 1631, 1644, 1657, 1665, 1668, + 1683, 1714, 1718, 1724, 1732, 1748, 1752, 1756, 1757, 1763, + 1764, 1765, 1766, 1767, 1771, 1772, 1772, 1772, 1780, 1781, + 1786, 1789, 1797, 1800, 1806, 1807, 1811, 1819, 1823, 1833, + 1838, 1855, 1855, 1860, 1860, 1867, 1867, 1875, 1878, 1884, + 1887, 1893, 1897, 1904, 1911, 1918, 1925, 1936, 1945, 1949, + 1956, 1959, 1965, 1965 +}; +#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, 102, 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, 116, 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, 123, 40, 41, 42, 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[] = +{ + 1225, 36, -250, -250, -250, 150, -250, -250, -250, -250, + -250, -250, -250, -250, -250, -250, -250, -250, -250, -250, + -250, -250, -250, -250, -250, -33, -250, -250, -250, -250, + -250, -60, -22, -17, 21, -62, -250, 22, 1266, -250, + 1290, -250, 11, -250, 1138, -250, -250, -250, -250, 1290, + 14, 1266, -250, 27, -250, 34, 41, -250, -250, -250, + -250, 1266, 129, 61, -250, 17, -250, -250, 908, -250, + -250, 31, 1266, 72, 1042, -250, 283, -250, -250, -250, + -250, 90, 1266, -46, -250, 194, 908, 65, -250, -250, + -250, -250, 908, 908, 908, -250, -250, -250, -250, -250, + -40, -250, -250, -250, 80, -25, 975, 87, -250, 908, + 35, 13, -250, -26, 68, -250, -250, -250, 110, 109, + -54, -250, 96, -250, -250, 1083, 98, 33, -250, -250, + -250, 91, 92, -250, 104, 107, 99, 760, 108, 105, + -250, -250, 24, -250, -250, 37, -250, -60, 112, -250, + -250, -250, -250, 365, -250, -250, -250, -250, 111, -250, + -250, 827, 908, -250, 113, -250, -250, -250, -250, 4, + -250, -250, 908, 1179, -250, -250, 908, 114, -250, -250, + -250, 908, 908, 908, 908, 908, 908, 908, 908, 908, + 908, 908, 908, 908, 908, -250, -250, 908, 72, -250, + -250, -250, 447, -250, 908, -250, -250, 42, -250, -250, + 447, -250, -250, -250, -250, -250, 908, 908, -250, -250, + -250, 908, -250, 115, -250, -250, -250, 116, 117, -250, + 120, -250, -250, -250, -250, 35, 35, -250, -250, -250, + -250, -26, -26, -250, 110, 109, 51, 119, -250, 144, + 611, 23, -250, 693, 447, -250, -250, 122, -250, -250, + 908, -250, 123, -250, -250, 693, 447, 117, 153, 126, + 128, -250, -250, 908, -250, 127, 137, 171, -250, 130, + 529, -250, 28, 908, 529, 447, 908, -250, -250, -250, + 131, 117, -250, -250, -250, -250 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -250, -250, -250, -250, -250, -250, -250, 39, -250, -250, + -250, -250, -45, -250, -18, -250, -79, -30, -250, -250, + -250, 38, 52, 20, -250, -63, -85, -250, -92, -71, + 6, 9, -250, -250, -250, 132, 172, 166, 148, -250, + -250, -246, -21, 0, 226, -24, -250, -250, 162, -66, + -250, 45, -159, -3, -136, -249, -250, -250, -250, -36, + 196, 46, 1, -250, -250, -13, -250, -250, -250, -250, + -250, -250, -250, -250, -250, 211, -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 -76 +static const yytype_int16 yytable[] = +{ + 39, 165, 169, 224, 193, 121, 30, 268, 130, 31, + 50, 170, 171, 62, 164, 63, 67, 220, 64, 268, + 52, 178, 121, 108, 56, 71, 161, 185, 186, 6, + 7, 287, 172, 162, 62, 287, 173, 56, 66, 194, + 108, 51, 6, 7, 39, 207, 175, 167, 168, 54, + 30, 73, 176, 31, 57, 58, 59, 23, 24, 130, + 55, 81, 187, 188, 180, 65, 249, 57, 58, 59, + 23, 24, 73, 47, 73, 226, 148, 165, 47, 48, + 228, 217, 81, 68, 211, 212, 213, 84, 72, 85, + 223, 232, -75, 214, 266, 183, 86, 184, 121, 290, + 217, 76, 246, 215, 83, 217, 237, 238, 239, 240, + 198, 124, 251, 199, 217, 126, 108, 218, 220, 217, + 181, 182, 252, 189, 190, 73, 247, 294, 217, 260, + 277, 255, 256, 158, 121, -26, 233, 234, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 293, + 257, 174, 108, 148, 2, 3, 4, 179, 121, 241, + 242, 267, 57, 58, 59, 235, 236, 191, 192, 195, + 197, 200, 201, 267, 203, 272, 108, 204, 208, 205, + 209, 282, -25, 221, 262, -20, 225, 285, 258, 259, + -27, 291, 261, 273, 217, 271, 279, 280, 2, 3, + 4, 165, 148, 281, 8, 9, 10, 283, 284, 286, + 148, 295, 231, 245, 159, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 78, 82, 243, + 160, 49, 25, 26, 125, 27, 28, 87, 29, 88, + 89, 90, 91, 248, 244, 92, 93, 263, 292, 77, + 148, 264, 274, 148, 148, 70, 254, 0, 0, 0, + 0, 0, 0, 0, 94, 148, 148, 163, 0, 0, + 0, 0, 0, 0, 0, 95, 96, 0, 97, 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, 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, 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, + 206, 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, + 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, 0, 0, 0, 0, 0, 0, 0, 95, 96, + 0, 97, 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, 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, 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, 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, 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, 0, 0, 0, 0, 25, 26, 0, + 27, 28, 229, 29, 0, 0, 0, 230, 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, 0, 29 +}; + +static const yytype_int16 yycheck[] = +{ + 0, 86, 94, 162, 58, 68, 0, 253, 74, 0, + 43, 51, 52, 34, 85, 77, 40, 153, 80, 265, + 80, 106, 85, 68, 3, 49, 72, 53, 54, 8, + 9, 280, 72, 79, 55, 284, 76, 3, 38, 93, + 85, 74, 8, 9, 44, 137, 71, 92, 93, 71, + 44, 51, 77, 44, 33, 34, 35, 36, 37, 125, + 77, 61, 88, 89, 109, 43, 202, 33, 34, 35, + 36, 37, 72, 37, 74, 71, 76, 162, 37, 43, + 172, 77, 82, 72, 60, 61, 62, 70, 74, 72, + 161, 176, 71, 69, 71, 82, 79, 84, 161, 71, + 77, 74, 194, 79, 43, 77, 185, 186, 187, 188, + 77, 80, 204, 80, 77, 43, 161, 80, 254, 77, + 85, 86, 80, 55, 56, 125, 197, 286, 77, 78, + 266, 216, 217, 43, 197, 70, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, 285, + 221, 71, 197, 153, 4, 5, 6, 70, 221, 189, + 190, 253, 33, 34, 35, 183, 184, 57, 59, 73, + 72, 80, 80, 265, 70, 260, 221, 70, 70, 80, + 75, 273, 70, 72, 40, 71, 73, 16, 73, 73, + 70, 283, 73, 70, 77, 73, 43, 71, 4, 5, + 6, 286, 202, 75, 10, 11, 12, 80, 71, 79, + 210, 80, 173, 193, 82, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 55, 62, 191, + 82, 5, 38, 39, 72, 41, 42, 43, 44, 45, + 46, 47, 48, 198, 192, 51, 52, 250, 284, 53, + 250, 250, 265, 253, 254, 44, 210, -1, -1, -1, + -1, -1, -1, -1, 70, 265, 266, 73, -1, -1, + -1, -1, -1, -1, -1, 81, 82, -1, 84, -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, 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, 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, + 80, 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, + 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, -1, -1, -1, -1, -1, -1, -1, 81, 82, + -1, 84, 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, -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, 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, 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, -1, -1, -1, -1, 38, 39, -1, + 41, 42, 43, 44, -1, -1, -1, 48, 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, -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, 137, 80, 142, 43, 144, 145, 75, + 143, 13, 14, 15, 17, 18, 19, 20, 40, 74, + 75, 80, 106, 119, 120, 122, 124, 125, 137, 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 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 /* 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(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((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 + // + if ((yyvsp[(1) - (1)].interm.type).array) { + // Constructors for arrays are not allowed. + context->error((yyvsp[(1) - (1)].interm.type).line, "cannot construct this type", "array", ""); + context->recover(); + (yyvsp[(1) - (1)].interm.type).setArray(false); + } + + 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(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); + + 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).line, (yyval.interm).type.precision, (yyvsp[(1) - (1)].interm).type.type)) { + context->recover(); + } + } + ;} + break; + + case 92: + + { + (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermNode, context->intermediate.addSymbol(0, *(yyvsp[(3) - (3)].lex).string, TType((yyvsp[(1) - (3)].interm).type), (yyvsp[(3) - (3)].lex).line), (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(); + + if (context->nonInitErrorCheck((yyvsp[(3) - (3)].lex).line, *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type)) + context->recover(); + ;} + 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; + 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(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: + + { + (yyval.interm).intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, *(yyvsp[(2) - (2)].lex).string, TType((yyvsp[(1) - (2)].interm.type)), (yyvsp[(2) - (2)].lex).line), (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); + + if (context->nonInitErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type)) + context->recover(); + ;} + break; + + case 98: + + { + (yyval.interm).intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, *(yyvsp[(2) - (4)].lex).string, TType((yyvsp[(1) - (4)].interm.type)), (yyvsp[(2) - (4)].lex).line), (yyvsp[(2) - (4)].lex).line); + + if (context->structQualifierErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type))) + context->recover(); + + if (context->nonInitConstErrorCheck((yyvsp[(2) - (4)].lex).line, *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type))) + context->recover(); + + (yyval.interm).type = (yyvsp[(1) - (4)].interm.type); + + if (context->arrayTypeErrorCheck((yyvsp[(3) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type)) || context->arrayQualifierErrorCheck((yyvsp[(3) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type))) + context->recover(); + else { + (yyvsp[(1) - (4)].interm.type).setArray(true); + TVariable* variable; + if (context->arrayErrorCheck((yyvsp[(3) - (4)].lex).line, *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), variable)) + context->recover(); + } + ;} + 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); + (yyval.interm).intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, *(yyvsp[(2) - (5)].lex).string, type, (yyvsp[(2) - (5)].lex).line), (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; + if (context->arrayErrorCheck((yyvsp[(3) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), variable)) + context->recover(); + } + ;} + 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); + ;} + 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((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); + + // 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); + (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); + (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((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((yyvsp[(5) - (7)].interm.nodePair).node1), reinterpret_cast((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(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); + ;} + 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 0000000..05cbfd4 --- /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 1489 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 index db042dd..798a69a 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/intermOut.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/intermOut.cpp @@ -21,8 +21,8 @@ // class TOutputTraverser : public TIntermTraverser { public: - TOutputTraverser(TInfoSink& i) : infoSink(i) { } - TInfoSink& infoSink; + TOutputTraverser(TInfoSinkBase& i) : sink(i) { } + TInfoSinkBase& sink; protected: void visitSymbol(TIntermSymbol*); @@ -56,14 +56,14 @@ TString TType::getCompleteString() const // Helper functions for printing, not part of traversing. // -void OutputTreeText(TInfoSink& infoSink, TIntermNode* node, const int depth) +void OutputTreeText(TInfoSinkBase& sink, TIntermNode* node, const int depth) { int i; - infoSink.debug.location(node->getLine()); + sink.location(node->getLine()); for (i = 0; i < depth; ++i) - infoSink.debug << " "; + sink << " "; } // @@ -77,226 +77,226 @@ void OutputTreeText(TInfoSink& infoSink, TIntermNode* node, const int depth) void TOutputTraverser::visitSymbol(TIntermSymbol* node) { - OutputTreeText(infoSink, node, depth); + OutputTreeText(sink, node, depth); - infoSink.debug << "'" << node->getSymbol() << "' "; - infoSink.debug << "(" << node->getCompleteString() << ")\n"; + sink << "'" << node->getSymbol() << "' "; + sink << "(" << node->getCompleteString() << ")\n"; } bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node) { - TInfoSink& out = infoSink; + TInfoSinkBase& out = sink; OutputTreeText(out, node, depth); switch (node->getOp()) { - case EOpAssign: out.debug << "move second child to first child"; break; - case EOpInitialize: out.debug << "initialize first child with second child"; break; - case EOpAddAssign: out.debug << "add second child into first child"; break; - case EOpSubAssign: out.debug << "subtract second child into first child"; break; - case EOpMulAssign: out.debug << "multiply second child into first child"; break; - case EOpVectorTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break; - case EOpVectorTimesScalarAssign: out.debug << "vector scale second child into first child"; break; - case EOpMatrixTimesScalarAssign: out.debug << "matrix scale second child into first child"; break; - case EOpMatrixTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break; - case EOpDivAssign: out.debug << "divide second child into first child"; break; - case EOpIndexDirect: out.debug << "direct index"; break; - case EOpIndexIndirect: out.debug << "indirect index"; break; - case EOpIndexDirectStruct: out.debug << "direct index for structure"; break; - case EOpVectorSwizzle: out.debug << "vector swizzle"; break; - - case EOpAdd: out.debug << "add"; break; - case EOpSub: out.debug << "subtract"; break; - case EOpMul: out.debug << "component-wise multiply"; break; - case EOpDiv: out.debug << "divide"; break; - case EOpEqual: out.debug << "Compare Equal"; break; - case EOpNotEqual: out.debug << "Compare Not Equal"; break; - case EOpLessThan: out.debug << "Compare Less Than"; break; - case EOpGreaterThan: out.debug << "Compare Greater Than"; break; - case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break; - case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break; - - case EOpVectorTimesScalar: out.debug << "vector-scale"; break; - case EOpVectorTimesMatrix: out.debug << "vector-times-matrix"; break; - case EOpMatrixTimesVector: out.debug << "matrix-times-vector"; break; - case EOpMatrixTimesScalar: out.debug << "matrix-scale"; break; - case EOpMatrixTimesMatrix: out.debug << "matrix-multiply"; break; - - case EOpLogicalOr: out.debug << "logical-or"; break; - case EOpLogicalXor: out.debug << "logical-xor"; break; - case EOpLogicalAnd: out.debug << "logical-and"; break; - default: out.debug << ""; + 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 << ""; } - out.debug << " (" << node->getCompleteString() << ")"; + out << " (" << node->getCompleteString() << ")"; - out.debug << "\n"; + out << "\n"; return true; } bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node) { - TInfoSink& out = infoSink; + TInfoSinkBase& out = sink; OutputTreeText(out, node, depth); switch (node->getOp()) { - case EOpNegative: out.debug << "Negate value"; break; + case EOpNegative: out << "Negate value"; break; case EOpVectorLogicalNot: - case EOpLogicalNot: out.debug << "Negate conditional"; break; - - case EOpPostIncrement: out.debug << "Post-Increment"; break; - case EOpPostDecrement: out.debug << "Post-Decrement"; break; - case EOpPreIncrement: out.debug << "Pre-Increment"; break; - case EOpPreDecrement: out.debug << "Pre-Decrement"; break; - - case EOpConvIntToBool: out.debug << "Convert int to bool"; break; - case EOpConvFloatToBool:out.debug << "Convert float to bool";break; - case EOpConvBoolToFloat:out.debug << "Convert bool to float";break; - case EOpConvIntToFloat: out.debug << "Convert int to float"; break; - case EOpConvFloatToInt: out.debug << "Convert float to int"; break; - case EOpConvBoolToInt: out.debug << "Convert bool to int"; break; - - case EOpRadians: out.debug << "radians"; break; - case EOpDegrees: out.debug << "degrees"; break; - case EOpSin: out.debug << "sine"; break; - case EOpCos: out.debug << "cosine"; break; - case EOpTan: out.debug << "tangent"; break; - case EOpAsin: out.debug << "arc sine"; break; - case EOpAcos: out.debug << "arc cosine"; break; - case EOpAtan: out.debug << "arc tangent"; break; - - case EOpExp: out.debug << "exp"; break; - case EOpLog: out.debug << "log"; break; - case EOpExp2: out.debug << "exp2"; break; - case EOpLog2: out.debug << "log2"; break; - case EOpSqrt: out.debug << "sqrt"; break; - case EOpInverseSqrt: out.debug << "inverse sqrt"; break; - - case EOpAbs: out.debug << "Absolute value"; break; - case EOpSign: out.debug << "Sign"; break; - case EOpFloor: out.debug << "Floor"; break; - case EOpCeil: out.debug << "Ceiling"; break; - case EOpFract: out.debug << "Fraction"; break; - - case EOpLength: out.debug << "length"; break; - case EOpNormalize: out.debug << "normalize"; break; - // case EOpDPdx: out.debug << "dPdx"; break; - // case EOpDPdy: out.debug << "dPdy"; break; - // case EOpFwidth: out.debug << "fwidth"; break; - - case EOpAny: out.debug << "any"; break; - case EOpAll: out.debug << "all"; break; - - default: out.debug.message(EPrefixError, "Bad unary op"); + 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.debug << " (" << node->getCompleteString() << ")"; + out << " (" << node->getCompleteString() << ")"; - out.debug << "\n"; + out << "\n"; return true; } bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node) { - TInfoSink& out = infoSink; + TInfoSinkBase& out = sink; if (node->getOp() == EOpNull) { - out.debug.message(EPrefixError, "node is still EOpNull!"); + out.message(EPrefixError, "node is still EOpNull!"); return true; } OutputTreeText(out, node, depth); switch (node->getOp()) { - case EOpSequence: out.debug << "Sequence\n"; return true; - case EOpComma: out.debug << "Comma\n"; return true; - case EOpFunction: out.debug << "Function Definition: " << node->getName(); break; - case EOpFunctionCall: out.debug << "Function Call: " << node->getName(); break; - case EOpParameters: out.debug << "Function Parameters: "; break; - - case EOpConstructFloat: out.debug << "Construct float"; break; - case EOpConstructVec2: out.debug << "Construct vec2"; break; - case EOpConstructVec3: out.debug << "Construct vec3"; break; - case EOpConstructVec4: out.debug << "Construct vec4"; break; - case EOpConstructBool: out.debug << "Construct bool"; break; - case EOpConstructBVec2: out.debug << "Construct bvec2"; break; - case EOpConstructBVec3: out.debug << "Construct bvec3"; break; - case EOpConstructBVec4: out.debug << "Construct bvec4"; break; - case EOpConstructInt: out.debug << "Construct int"; break; - case EOpConstructIVec2: out.debug << "Construct ivec2"; break; - case EOpConstructIVec3: out.debug << "Construct ivec3"; break; - case EOpConstructIVec4: out.debug << "Construct ivec4"; break; - case EOpConstructMat2: out.debug << "Construct mat2"; break; - case EOpConstructMat3: out.debug << "Construct mat3"; break; - case EOpConstructMat4: out.debug << "Construct mat4"; break; - case EOpConstructStruct: out.debug << "Construct structure"; break; - - case EOpLessThan: out.debug << "Compare Less Than"; break; - case EOpGreaterThan: out.debug << "Compare Greater Than"; break; - case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break; - case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break; - case EOpVectorEqual: out.debug << "Equal"; break; - case EOpVectorNotEqual: out.debug << "NotEqual"; break; - - case EOpMod: out.debug << "mod"; break; - case EOpPow: out.debug << "pow"; break; - - case EOpAtan: out.debug << "arc tangent"; break; - - case EOpMin: out.debug << "min"; break; - case EOpMax: out.debug << "max"; break; - case EOpClamp: out.debug << "clamp"; break; - case EOpMix: out.debug << "mix"; break; - case EOpStep: out.debug << "step"; break; - case EOpSmoothStep: out.debug << "smoothstep"; break; - - case EOpDistance: out.debug << "distance"; break; - case EOpDot: out.debug << "dot-product"; break; - case EOpCross: out.debug << "cross-product"; break; - case EOpFaceForward: out.debug << "face-forward"; break; - case EOpReflect: out.debug << "reflect"; break; - case EOpRefract: out.debug << "refract"; break; - case EOpMul: out.debug << "component-wise multiply"; break; - - default: out.debug.message(EPrefixError, "Bad aggregation op"); + 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.debug << " (" << node->getCompleteString() << ")"; + out << " (" << node->getCompleteString() << ")"; - out.debug << "\n"; + out << "\n"; return true; } bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node) { - TInfoSink& out = infoSink; + TInfoSinkBase& out = sink; OutputTreeText(out, node, depth); - out.debug << "Test condition and select"; - out.debug << " (" << node->getCompleteString() << ")\n"; + out << "Test condition and select"; + out << " (" << node->getCompleteString() << ")\n"; ++depth; - OutputTreeText(infoSink, node, depth); - out.debug << "Condition\n"; + OutputTreeText(sink, node, depth); + out << "Condition\n"; node->getCondition()->traverse(this); - OutputTreeText(infoSink, node, depth); + OutputTreeText(sink, node, depth); if (node->getTrueBlock()) { - out.debug << "true case\n"; + out << "true case\n"; node->getTrueBlock()->traverse(this); } else - out.debug << "true case is null\n"; + out << "true case is null\n"; if (node->getFalseBlock()) { - OutputTreeText(infoSink, node, depth); - out.debug << "false case\n"; + OutputTreeText(sink, node, depth); + out << "false case\n"; node->getFalseBlock()->traverse(this); } @@ -307,7 +307,7 @@ bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node) void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) { - TInfoSink& out = infoSink; + TInfoSinkBase& out = sink; int size = node->getType().getObjectSize(); @@ -316,23 +316,23 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) switch (node->getUnionArrayPointer()[i].getType()) { case EbtBool: if (node->getUnionArrayPointer()[i].getBConst()) - out.debug << "true"; + out << "true"; else - out.debug << "false"; + out << "false"; - out.debug << " (" << "const bool" << ")"; - out.debug << "\n"; + out << " (" << "const bool" << ")"; + out << "\n"; break; case EbtFloat: - out.debug << node->getUnionArrayPointer()[i].getFConst(); - out.debug << " (const float)\n"; + out << node->getUnionArrayPointer()[i].getFConst(); + out << " (const float)\n"; break; case EbtInt: - out.debug << node->getUnionArrayPointer()[i].getIConst(); - out.debug << " (const int)\n"; + out << node->getUnionArrayPointer()[i].getIConst(); + out << " (const int)\n"; break; default: - out.info.message(EPrefixInternalError, "Unknown constant", node->getLine()); + out.message(EPrefixInternalError, "Unknown constant", node->getLine()); break; } } @@ -340,35 +340,35 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node) { - TInfoSink& out = infoSink; + TInfoSinkBase& out = sink; OutputTreeText(out, node, depth); - out.debug << "Loop with condition "; - if (! node->testFirst()) - out.debug << "not "; - out.debug << "tested first\n"; + out << "Loop with condition "; + if (node->getType() == ELoopDoWhile) + out << "not "; + out << "tested first\n"; ++depth; - OutputTreeText(infoSink, node, depth); - if (node->getTest()) { - out.debug << "Loop Condition\n"; - node->getTest()->traverse(this); + OutputTreeText(sink, node, depth); + if (node->getCondition()) { + out << "Loop Condition\n"; + node->getCondition()->traverse(this); } else - out.debug << "No loop condition\n"; + out << "No loop condition\n"; - OutputTreeText(infoSink, node, depth); + OutputTreeText(sink, node, depth); if (node->getBody()) { - out.debug << "Loop Body\n"; + out << "Loop Body\n"; node->getBody()->traverse(this); } else - out.debug << "No loop body\n"; + out << "No loop body\n"; - if (node->getTerminal()) { - OutputTreeText(infoSink, node, depth); - out.debug << "Loop Terminal Expression\n"; - node->getTerminal()->traverse(this); + if (node->getExpression()) { + OutputTreeText(sink, node, depth); + out << "Loop Terminal Expression\n"; + node->getExpression()->traverse(this); } --depth; @@ -378,25 +378,25 @@ bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node) bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node) { - TInfoSink& out = infoSink; + TInfoSinkBase& out = sink; OutputTreeText(out, node, depth); switch (node->getFlowOp()) { - case EOpKill: out.debug << "Branch: Kill"; break; - case EOpBreak: out.debug << "Branch: Break"; break; - case EOpContinue: out.debug << "Branch: Continue"; break; - case EOpReturn: out.debug << "Branch: Return"; break; - default: out.debug << "Branch: Unknown Branch"; break; + 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.debug << " with expression\n"; + out << " with expression\n"; ++depth; node->getExpression()->traverse(this); --depth; } else - out.debug << "\n"; + out << "\n"; return false; } @@ -411,7 +411,7 @@ void TIntermediate::outputTree(TIntermNode* root) if (root == 0) return; - TOutputTraverser it(infoSink); + 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 index d262905..f9fa1de 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/intermediate.h +++ b/Source/ThirdParty/ANGLE/src/compiler/intermediate.h @@ -129,9 +129,9 @@ enum TOperator { EOpReflect, EOpRefract, - //EOpDPdx, // Fragment only, OES_standard_derivatives extension - //EOpDPdy, // Fragment only, OES_standard_derivatives extension - //EOpFwidth, // Fragment only, OES_standard_derivatives extension + EOpDFdx, // Fragment only, OES_standard_derivatives extension + EOpDFdy, // Fragment only, OES_standard_derivatives extension + EOpFwidth, // Fragment only, OES_standard_derivatives extension EOpMatrixTimesMatrix, @@ -184,6 +184,8 @@ enum TOperator { EOpDivAssign, }; +extern const char* getOperatorString(TOperator op); + class TIntermTraverser; class TIntermAggregate; class TIntermBinary; @@ -262,30 +264,38 @@ protected: // // Handle for, do-while, and while loops. // +enum TLoopType { + ELoopFor, + ELoopWhile, + ELoopDoWhile, +}; + class TIntermLoop : public TIntermNode { public: - TIntermLoop(TIntermNode *init, TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) : - init(init), - body(aBody), - test(aTest), - terminal(aTerminal), - first(testFirst) { } + TIntermLoop(TLoopType aType, + TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr, + TIntermNode* aBody) : + type(aType), + init(aInit), + cond(aCond), + expr(aExpr), + body(aBody) { } virtual TIntermLoop* getAsLoopNode() { return this; } virtual void traverse(TIntermTraverser*); - TIntermNode *getInit() { return init; } - TIntermNode *getBody() { return body; } - TIntermTyped *getTest() { return test; } - TIntermTyped *getTerminal() { return terminal; } - bool testFirst() { return first; } + TLoopType getType() const { return type; } + TIntermNode* getInit() { return init; } + TIntermTyped* getCondition() { return cond; } + TIntermTyped* getExpression() { return expr; } + TIntermNode* getBody() { return body; } protected: - TIntermNode *init; - TIntermNode *body; // code to loop over - TIntermTyped *test; // exit condition associated with loop, could be 0 for 'for' loops - TIntermTyped *terminal; // exists for for-loops - bool first; // true for while and for, not for do-while + TLoopType type; + TIntermNode* init; // for-loop initialization + TIntermTyped* cond; // loop exit condition + TIntermTyped* expr; // for-loop expression + TIntermNode* body; // loop body }; // @@ -404,6 +414,7 @@ protected: typedef TVector TIntermSequence; typedef TVector TQualifierList; +typedef TMap TPragmaTable; // // Nodes that operate on an arbitrary sized set of children. // @@ -417,12 +428,13 @@ public: virtual void traverse(TIntermTraverser*); TIntermSequence& getSequence() { return sequence; } + void setName(const TString& n) { name = n; } const TString& getName() const { return name; } void setUserDefined() { userDefined = true; } bool isUserDefined() { return userDefined; } - TQualifierList& getQualifier() { return qualifier; } + void setOptimize(bool o) { optimize = o; } bool getOptimize() { return optimize; } void setDebug(bool d) { debug = d; } @@ -434,9 +446,9 @@ protected: TIntermAggregate(const TIntermAggregate&); // disallow copy constructor TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator TIntermSequence sequence; - TQualifierList qualifier; TString name; bool userDefined; // used for user defined function names + bool optimize; bool debug; TPragmaTable *pragmaTable; diff --git a/Source/ThirdParty/ANGLE/src/compiler/localintermediate.h b/Source/ThirdParty/ANGLE/src/compiler/localintermediate.h index 5fd4c69..56890bd 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/localintermediate.h +++ b/Source/ThirdParty/ANGLE/src/compiler/localintermediate.h @@ -40,11 +40,11 @@ public: TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, TSourceLoc); TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ; bool parseConstTree(TSourceLoc, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false); - TIntermNode* addLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, TSourceLoc); + TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, TSourceLoc); TIntermBranch* addBranch(TOperator, TSourceLoc); TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc); TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc); - bool postProcess(TIntermNode*, EShLanguage); + bool postProcess(TIntermNode*); void remove(TIntermNode*); void outputTree(TIntermNode*); diff --git a/Source/ThirdParty/ANGLE/src/compiler/osinclude.h b/Source/ThirdParty/ANGLE/src/compiler/osinclude.h index d887914..1af5064 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/osinclude.h +++ b/Source/ThirdParty/ANGLE/src/compiler/osinclude.h @@ -8,8 +8,8 @@ #define __OSINCLUDE_H // -// This file contains contains the window's specific datatypes and -// declares any windows specific functions. +// This file contains contains os-specific datatypes and +// declares any os-specific functions. // #if defined(_WIN32) || defined(_WIN64) @@ -22,7 +22,9 @@ #error Unsupported platform. #endif -#if defined(ANGLE_OS_WIN) +#if defined(ANGLE_USE_NSPR) +#include "prthread.h" +#elif defined(ANGLE_OS_WIN) #define STRICT #define VC_EXTRALEAN 1 #include @@ -30,20 +32,24 @@ #include #include #include -#endif // ANGLE_OS_WIN +#endif // ANGLE_USE_NSPR + #include "compiler/debug.h" // // Thread Local Storage Operations // -#if defined(ANGLE_OS_WIN) +#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_OS_WIN +#endif // ANGLE_USE_NSPR OS_TLSIndex OS_AllocTLSIndex(); bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue); @@ -51,8 +57,10 @@ bool OS_FreeTLSIndex(OS_TLSIndex nIndex); inline void* OS_GetTLSValue(OS_TLSIndex nIndex) { - assert(nIndex != OS_INVALID_TLS_INDEX); -#if defined(ANGLE_OS_WIN) + 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); 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 0000000..f63d81e --- /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/preprocessor/compile.h b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/compile.h index 5bfa902..69e3425 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/compile.h +++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/compile.h @@ -89,10 +89,10 @@ struct CPPStruct_Rec { // Globals used to communicate between PaParseStrings() and yy_input()and // also across the files.(gen_glslang.cpp and scanner.c) // - int PaWhichStr; // which string we're parsing - int* PaStrLen; // array of lengths of the PaArgv strings - int PaArgc; // count of strings in the array - char** PaArgv; // our array of strings to parse + 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; }; diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.c b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.c index f15c56d..204a213 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.c +++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/cpp.c @@ -191,6 +191,9 @@ static int CPPdefine(yystypepp * yylvalpp) 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); @@ -267,9 +270,13 @@ static int CPPelse(int matchelse, yystypepp * yylvalpp) while (token > 0) { if (token != '#') { - while (token != '\n') + 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; } @@ -295,8 +302,13 @@ static int CPPelse(int matchelse, yystypepp * yylvalpp) token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token != '\n') { CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline"); - while (token != '\n') + 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; } @@ -467,9 +479,14 @@ static int CPPif(yystypepp * yylvalpp) { } token = eval(token, MIN_PREC, &res, &err, yylvalpp); if (token != '\n') { - CPPWarningToInfoLog("unexpected tokens following the preprocessor directive - expected a newline"); - while (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); @@ -495,8 +512,13 @@ static int CPPifdef(int defined, yystypepp * yylvalpp) token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token != '\n') { CPPWarningToInfoLog("unexpected tokens following #ifdef preprocessor directive - expected a newline"); - while (token != '\n') + 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); @@ -544,7 +566,10 @@ static int CPPerror(yystypepp * yylvalpp) { const char *message; while (token != '\n') { - if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){ + 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)); @@ -670,7 +695,7 @@ static int CPPextension(yystypepp * yylvalpp) { int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - char extensionName[80]; + char extensionName[MAX_SYMBOL_NAME_LEN + 1]; if(token=='\n'){ DecLineNumber(); @@ -682,7 +707,8 @@ static int CPPextension(yystypepp * yylvalpp) if (token != CPP_IDENTIFIER) CPPErrorToInfoLog("#extension"); - strcpy(extensionName, GetAtomString(atable, yylvalpp->sc_ident)); + 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 != ':') { @@ -726,8 +752,13 @@ int readCPPline(yystypepp * yylvalpp) token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token != '\n') { CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline"); - while (token != '\n') + 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{ @@ -743,8 +774,14 @@ int readCPPline(yystypepp * yylvalpp) } // 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') + 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; + break; + } + } token = CPPelse(0, yylvalpp); } else if (yylvalpp->sc_ident == endifAtom) { --cpp->elsetracker; diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/preprocess.h b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/preprocess.h index 0602c91..88d196f 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/preprocess.h +++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/preprocess.h @@ -42,10 +42,10 @@ TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \****************************************************************************/ -# include "compiler/preprocessor/slglobals.h" +#include "compiler/preprocessor/slglobals.h" extern CPPStruct *cpp; int InitCPPStruct(void); int InitScanner(CPPStruct *cpp); int InitAtomTable(AtomTable *atable, int htsize); -int ScanFromString(char *s); +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 index c77d271..7b399a0 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/scanner.c +++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/scanner.c @@ -45,6 +45,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // scanner.c // +#include #include #include #include @@ -52,13 +53,13 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #if 0 #include - #else +#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; @@ -133,49 +134,49 @@ int FreeScanner(void) */ static int str_getch(StringInputSrc *in) { - for(;;){ - if (*in->p){ - if (*in->p == '\n') { + 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; + } + 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') { + else { + *(in->p)='\0'; //this would take care of shifting to the previous string. + cpp->PaWhichStr--; + } + if (ch == '\n') { in->base.line--; DecLineNumber(); } } // str_ungetch -int ScanFromString(char *s) +int ScanFromString(const char *s) { - StringInputSrc *in = malloc(sizeof(StringInputSrc)); + StringInputSrc *in = malloc(sizeof(StringInputSrc)); memset(in, 0, sizeof(StringInputSrc)); - in->p = s; + in->p = (char*) s; in->base.line = 1; in->base.scan = byte_scan; in->base.getch = (int (*)(InputSrc *, yystypepp *))str_getch; @@ -190,119 +191,63 @@ int ScanFromString(char *s) /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////// Floating point constants: ///////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// -/* - * lBuildFloatValue() - Quick and dirty conversion to floating point. Since all - * we need is single precision this should be quite precise. - */ - -static float lBuildFloatValue(const char *str, int len, int exp) -{ - double val, expval, ten; - int ii, llen, absexp; - float rv; - - val = 0.0; - llen = len; - for (ii = 0; ii < len; ii++) - val = val*10.0 + (str[ii] - '0'); - if (exp != 0) { - absexp = exp > 0 ? exp : -exp; - expval = 1.0f; - ten = 10.0; - while (absexp) { - if (absexp & 1) - expval *= ten; - ten *= ten; - absexp >>= 1; - } - if (exp >= 0) { - val *= expval; - } else { - val /= expval; - } - } - rv = (float)val; - if (isinff(rv)) { - CPPErrorToInfoLog(" ERROR___FP_CONST_OVERFLOW"); - } - return rv; -} // lBuildFloatValue +#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(char *str, int len, int ch, yystypepp * yylvalpp) +static int lFloatConst(int ch, int len, yystypepp * yylvalpp) { - int HasDecimal, declen, exp, ExpSign; - int str_len; - float lval; - - HasDecimal = 0; - declen = 0; - exp = 0; - - str_len=len; + int alreadyComplained = 0; + assert((ch == '.') || (ch == 'e') || (ch == 'E')); + if (ch == '.') { - str[len++]=ch; - HasDecimal = 1; - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - while (ch >= '0' && ch <= '9') { - if (len < MAX_SYMBOL_NAME_LEN) { - declen++; - if (len > 0 || ch != '0') { - str[len] = ch; - len++;str_len++; - } - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - } else { - CPPErrorToInfoLog("ERROR___FP_CONST_TOO_LONG"); - len = 1,str_len=1; - } - } + 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') { - ExpSign = 1; - str[len++]=ch; + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == '+') { - str[len++]=ch; - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); } else if (ch == '-') { - ExpSign = -1; - str[len++]=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') { - exp = exp*10 + ch - '0'; - str[len++]=ch; + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); } } else { - CPPErrorToInfoLog("ERROR___ERROR_IN_EXPONENT"); + CPPErrorToInfoLog("EXPONENT INVALID"); } - exp *= ExpSign; } - - if (len == 0) { - lval = 0.0f; - strcpy(str,"0.0"); - } else { - str[len]='\0'; - lval = lBuildFloatValue(str, str_len, exp - declen); + 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"); } - // Suffix: - - yylvalpp->sc_fval = lval; - strcpy(yylvalpp->symbol_name,str); - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); return CPP_FLOATCONSTANT; } // lFloatConst @@ -312,29 +257,29 @@ static int lFloatConst(char *str, int len, int ch, yystypepp * yylvalpp) static int byte_scan(InputSrc *in, yystypepp * yylvalpp) { - char symbol_name[MAX_SYMBOL_NAME_LEN + 1]; char string_val[MAX_STRING_LEN + 1]; - int AlreadyComplained; + int 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 + return ch; // Single character token case EOF: return -1; - case 'A': case 'B': case 'C': case 'D': case 'E': + 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': @@ -347,39 +292,32 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp) case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': do { - if (len < MAX_SYMBOL_NAME_LEN) { - symbol_name[len] = ch; - len++; - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - } else { - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - } + 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 == '_'); - if (len >= MAX_SYMBOL_NAME_LEN) - len = MAX_SYMBOL_NAME_LEN - 1; - symbol_name[len] = '\0'; + assert(len <= MAX_SYMBOL_NAME_LEN); + yylvalpp->symbol_name[len] = '\0'; cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - yylvalpp->sc_ident = LookUpAddString(atable, symbol_name); + yylvalpp->sc_ident = LookUpAddString(atable, yylvalpp->symbol_name); return CPP_IDENTIFIER; break; case '0': - yylvalpp->symbol_name[len++] = ch; + APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch == 'x' || ch == 'X') { - yylvalpp->symbol_name[len++] = ch; + 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')) { - AlreadyComplained = 0; ival = 0; do { - yylvalpp->symbol_name[len++] = ch; - if (ival <= 0x0fffffff) { + 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') { @@ -388,74 +326,67 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp) ii = ch - 'a' + 10; } ival = (ival << 4) | ii; - } else { - if (!AlreadyComplained) - CPPErrorToInfoLog("ERROR___HEX_CONST_OVERFLOW"); - AlreadyComplained = 1; + } 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("ERROR___ERROR_IN_HEX_CONSTANT"); + 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; + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + yylvalpp->sc_int = ival; return CPP_INTCONSTANT; } else if (ch >= '0' && ch <= '7') { // octal integer constants - AlreadyComplained = 0; ival = 0; do { - yylvalpp->symbol_name[len++] = ch; - if (ival <= 0x1fffffff) { + if ((ival <= 0x1fffffff) && (len < MAX_SYMBOL_NAME_LEN)) { + yylvalpp->symbol_name[len++] = ch; ii = ch - '0'; ival = (ival << 3) | ii; - } else { - if (!AlreadyComplained) - CPPErrorToInfoLog("ERROR___OCT_CONST_OVERFLOW"); - AlreadyComplained = 1; + } 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(yylvalpp->symbol_name, len, ch, yylvalpp); + 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; + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + yylvalpp->sc_int = ival; return CPP_INTCONSTANT; } else { - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - ch = '0'; + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + ch = '0'; } // Fall through... case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': do { - if (len < MAX_SYMBOL_NAME_LEN) { - if (len > 0 || ch != '0') { - yylvalpp->symbol_name[len] = ch; - len++; - } - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - } + 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 == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') { - return lFloatConst(yylvalpp->symbol_name, len, ch, yylvalpp); + return lFloatConst(ch, len, yylvalpp); } else { + assert(len <= MAX_SYMBOL_NAME_LEN); yylvalpp->symbol_name[len] = '\0'; - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); ival = 0; - AlreadyComplained = 0; for (ii = 0; ii < len; ii++) { ch = yylvalpp->symbol_name[ii] - '0'; + ival = ival*10 + ch; if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) { - if (!AlreadyComplained) - CPPErrorToInfoLog("ERROR___INTEGER_CONST_OVERFLOW"); - AlreadyComplained = 1; + CPPErrorToInfoLog("INTEGER CONSTANT OVERFLOW"); + break; } - ival = ival*10 + ch; } yylvalpp->sc_int = ival; if(ival==0) @@ -608,7 +539,7 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp) ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch >= '0' && ch <= '9') { cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return lFloatConst(yylvalpp->symbol_name, 0, '.', yylvalpp); + return lFloatConst('.', 0, yylvalpp); } else { if (ch == '.') { return -1; // Special EOF hack @@ -633,14 +564,14 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp) while (ch != '*') { if (ch == '\n') nlcount++; if (ch == EOF) { - CPPErrorToInfoLog("ERROR___EOF_IN_COMMENT"); + CPPErrorToInfoLog("EOF IN COMMENT"); return -1; } ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); } ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); if (ch == EOF) { - CPPErrorToInfoLog("ERROR___EOF_IN_COMMENT"); + CPPErrorToInfoLog("EOF IN COMMENT"); return -1; } } while (ch != '/'); @@ -662,41 +593,40 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp) CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language"); return -1; } - if (len < MAX_STRING_LEN) { - string_val[len] = ch; - len++; - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - } + 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("ERROR___CPP_EOL_IN_STRING"); + CPPErrorToInfoLog("EOL IN STRING"); return ERROR_SY; } + break; } } } // byte_scan int yylex_CPP(char* buf, int maxSize) { - yystypepp yylvalpp; + yystypepp yylvalpp; int token = '\n'; for(;;) { char* tokenString = 0; token = cpp->currentInput->scan(cpp->currentInput, &yylvalpp); - if(check_EOF(token)) - return 0; + if(check_EOF(token)) + return 0; if (token == '#') { if (cpp->previous_token == '\n'|| cpp->previous_token == 0) { - token = readCPPline(&yylvalpp); + token = readCPPline(&yylvalpp); if(check_EOF(token)) return 0; - continue; + continue; } else { CPPErrorToInfoLog("preprocessor command must not be preceded by any other statement in that line"); return 0; @@ -708,30 +638,28 @@ int yylex_CPP(char* buf, int maxSize) cpp->pastFirstStatement = 1; continue; } - + if (token == '\n') continue; - - if (token == CPP_IDENTIFIER) { - cpp->pastFirstStatement = 1; + cpp->pastFirstStatement = 1; + + if (token == CPP_IDENTIFIER) { tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident); - } else if (token == CPP_FLOATCONSTANT||token == CPP_INTCONSTANT){ - cpp->pastFirstStatement = 1; + } else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){ tokenString = yylvalpp.symbol_name; - } else { - cpp->pastFirstStatement = 1; + } else { tokenString = GetStringOfAtom(atable,token); - } + } if (tokenString) { - if ((signed)strlen(tokenString) >= maxSize) { - cpp->tokensBeforeEOF = 1; - return maxSize; - } else if (strlen(tokenString) > 0) { - strcpy(buf, tokenString); - cpp->tokensBeforeEOF = 1; - return (int)strlen(tokenString); - } + int len = strlen(tokenString); + cpp->tokensBeforeEOF = 1; + if (len >= maxSize) { + return maxSize; + } else if (len > 0) { + strcpy(buf, tokenString); + return len; + } return 0; } @@ -745,7 +673,7 @@ int check_EOF(int token) { if(token==-1){ if(cpp->ifdepth >0){ - CPPErrorToInfoLog("#endif missing!! Compilation stopped"); + CPPErrorToInfoLog("#endif missing!! Compilation stopped"); cpp->CompileError=1; } return 1; diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/scanner.h b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/scanner.h index 571fe57..0fee20d 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/scanner.h +++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/scanner.h @@ -48,8 +48,9 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #if !defined(__SCANNER_H) #define __SCANNER_H 1 -#define MAX_SYMBOL_NAME_LEN 128 -#define MAX_STRING_LEN 512 +// These lengths do not include the NULL terminator. +#define MAX_SYMBOL_NAME_LEN 127 +#define MAX_STRING_LEN 511 #include "compiler/preprocessor/parser.h" @@ -59,8 +60,6 @@ typedef struct SourceLoc_Rec { unsigned short file, line; } SourceLoc; -int yyparse (void); - int yylex_CPP(char* buf, int maxSize); typedef struct InputSrc { @@ -73,7 +72,7 @@ typedef struct InputSrc { } InputSrc; int InitScanner(CPPStruct *cpp); // Intialise the cpp scanner. -int ScanFromString(char *); // Start scanning the input from the string mentioned. +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); diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/tokens.c b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/tokens.c index 057cce8..aa83d2f 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/tokens.c +++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/tokens.c @@ -52,6 +52,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "compiler/debug.h" #include "compiler/preprocessor/slglobals.h" +#include "compiler/util.h" /////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////// Preprocessor and Token Recorder and Playback: //////////////////////// @@ -224,8 +225,7 @@ void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp) case CPP_INTCONSTANT: str=yylvalpp->symbol_name; while (*str){ - lAddByte(pTok,(unsigned char) *str); - *str++; + lAddByte(pTok, (unsigned char) *str++); } lAddByte(pTok, 0); break; @@ -276,8 +276,7 @@ int ReadToken(TokenStream *pTok, yystypepp * yylvalpp) ch == '_') { if (len < MAX_SYMBOL_NAME_LEN) { - symbol_name[len] = ch; - len++; + symbol_name[len++] = ch; ch = lReadByte(pTok); } } @@ -291,7 +290,7 @@ int ReadToken(TokenStream *pTok, yystypepp * yylvalpp) while ((ch = lReadByte(pTok)) != 0) if (len < MAX_STRING_LEN) string_val[len++] = ch; - string_val[len] = 0; + string_val[len] = '\0'; yylvalpp->sc_ident = LookUpAddString(atable, string_val); break; case CPP_FLOATCONSTANT: @@ -300,15 +299,14 @@ int ReadToken(TokenStream *pTok, yystypepp * yylvalpp) while ((ch >= '0' && ch <= '9')||(ch=='e'||ch=='E'||ch=='.')||(ch=='+'||ch=='-')) { if (len < MAX_SYMBOL_NAME_LEN) { - symbol_name[len] = ch; - 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(yylvalpp->symbol_name); + yylvalpp->sc_fval=(float)atof_dot(yylvalpp->symbol_name); break; case CPP_INTCONSTANT: len = 0; @@ -316,8 +314,7 @@ int ReadToken(TokenStream *pTok, yystypepp * yylvalpp) while ((ch >= '0' && ch <= '9')) { if (len < MAX_SYMBOL_NAME_LEN) { - symbol_name[len] = ch; - len++; + symbol_name[len++] = ch; ch = lReadByte(pTok); } } diff --git a/Source/ThirdParty/ANGLE/src/compiler/unistd.h b/Source/ThirdParty/ANGLE/src/compiler/unistd.h deleted file mode 100644 index c7c9147..0000000 --- a/Source/ThirdParty/ANGLE/src/compiler/unistd.h +++ /dev/null @@ -1 +0,0 @@ -// This is a NULL file and is meant to be empty diff --git a/Source/ThirdParty/ANGLE/src/compiler/util.cpp b/Source/ThirdParty/ANGLE/src/compiler/util.cpp new file mode 100644 index 0000000..b46e4d0 --- /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 +#include + +#include "util.h" + +#ifdef _MSC_VER + #include +#else + #include +#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 0000000..35288b7 --- /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 index 21d4661..284f61d 100644 --- a/Source/ThirdParty/ANGLE/src/libEGL/Config.cpp +++ b/Source/ThirdParty/ANGLE/src/libEGL/Config.cpp @@ -94,13 +94,6 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter mBlueSize = 5; mAlphaSize = 0; break; - case D3DFMT_X1R5G5B5: - mBufferSize = 16; - mRedSize = 5; - mGreenSize = 5; - mBlueSize = 5; - mAlphaSize = 0; - break; case D3DFMT_X8R8G8B8: mBufferSize = 32; mRedSize = 8; diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp b/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp index e2802da..6f1a335 100644 --- a/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp +++ b/Source/ThirdParty/ANGLE/src/libEGL/Display.cpp @@ -17,7 +17,8 @@ #include "libEGL/main.h" -#define REF_RAST 0 // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros +#define REF_RAST 0 // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros +#define ENABLE_D3D9EX 1 // Enables use of the IDirect3D9Ex interface, when available namespace egl { @@ -40,7 +41,6 @@ Display::Display(HDC deviceContext) : mDc(deviceContext) mMinSwapInterval = 1; mMaxSwapInterval = 1; - setSwapInterval(1); } Display::~Display() @@ -77,7 +77,7 @@ bool Display::initialize() // Use Direct3D9Ex if available. Among other things, this version is less // inclined to report a lost context, for example when the user switches // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. - if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9ex))) + if (ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9ex))) { ASSERT(mD3d9ex); mD3d9ex->QueryInterface(IID_IDirect3D9, reinterpret_cast(&mD3d9)); @@ -95,11 +95,26 @@ bool Display::initialize() // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to } - HRESULT result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); - - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) + HRESULT result; + + // Give up on getting device caps after about one second. + for (int i = 0; i < 10; ++i) { - return error(EGL_BAD_ALLOC, false); + 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)) @@ -108,6 +123,14 @@ bool Display::initialize() 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; @@ -123,7 +146,7 @@ bool Display::initialize() // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value. D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, - D3DFMT_X1R5G5B5, + // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format D3DFMT_X8R8G8B8 }; @@ -183,13 +206,6 @@ bool Display::initialize() mConfigSet.mSet.insert(configuration); } - - if (!createDevice()) - { - terminate(); - - return false; - } } if (!isInitialized()) @@ -199,23 +215,34 @@ bool Display::initialize() return false; } + 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() { - for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) + while (!mSurfaceSet.empty()) { - delete *surface; + destroySurface(*mSurfaceSet.begin()); } - for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++) + while (!mContextSet.empty()) { - glDestroyContext(*context); + destroyContext(*mContextSet.begin()); } if (mDevice) { + // If the device is lost, reset it first to prevent leaving the driver in an unstable state + if (FAILED(mDevice->TestCooperativeLevel())) + { + resetDevice(); + } + mDevice->Release(); mDevice = NULL; } @@ -314,33 +341,12 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) bool Display::createDevice() { - static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); - static const TCHAR className[] = TEXT("STATIC"); - - mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); - - D3DPRESENT_PARAMETERS presentParameters = {0}; - - // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters. - presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN; - presentParameters.BackBufferCount = 1; - presentParameters.BackBufferFormat = D3DFMT_UNKNOWN; - presentParameters.BackBufferWidth = 1; - presentParameters.BackBufferHeight = 1; - presentParameters.EnableAutoDepthStencil = FALSE; - presentParameters.Flags = 0; - presentParameters.hDeviceWindow = mDeviceWindow; - presentParameters.MultiSampleQuality = 0; - presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; - presentParameters.PresentationInterval = convertInterval(mMinSwapInterval); - presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; - presentParameters.Windowed = TRUE; - + 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) + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) { return error(EGL_BAD_ALLOC, false); } @@ -349,14 +355,13 @@ bool Display::createDevice() { result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) + if (FAILED(result)) { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST); return error(EGL_BAD_ALLOC, false); } } - ASSERT(SUCCEEDED(result)); - // Permanent non-default states mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); @@ -365,6 +370,29 @@ bool Display::createDevice() 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; +} + Surface *Display::createWindowSurface(HWND window, EGLConfig config) { const Config *configuration = mConfigSet.get(config); @@ -377,6 +405,27 @@ Surface *Display::createWindowSurface(HWND window, EGLConfig config) EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext) { + if (!mDevice) + { + if (!createDevice()) + { + return NULL; + } + } + else if (FAILED(mDevice->TestCooperativeLevel())) // Lost device + { + 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); @@ -395,6 +444,14 @@ void Display::destroyContext(gl::Context *context) { glDestroyContext(context); mContextSet.erase(context); + + if (mContextSet.empty() && mDevice && FAILED(mDevice->TestCooperativeLevel())) // Last context of a lost device + { + for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) + { + (*surface)->release(); + } + } } bool Display::isInitialized() @@ -430,37 +487,26 @@ bool Display::hasExistingWindowSurface(HWND window) return false; } -void Display::setSwapInterval(GLint interval) +EGLint Display::getMinSwapInterval() { - mSwapInterval = interval; - mSwapInterval = std::max(mSwapInterval, mMinSwapInterval); - mSwapInterval = std::min(mSwapInterval, mMaxSwapInterval); - - mPresentInterval = convertInterval(mSwapInterval); + return mMinSwapInterval; } -DWORD Display::getPresentInterval() +EGLint Display::getMaxSwapInterval() { - return mPresentInterval; + return mMaxSwapInterval; } -DWORD Display::convertInterval(GLint interval) +IDirect3DDevice9 *Display::getDevice() { - switch(interval) + if (!mDevice) { - 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(); + if (!createDevice()) + { + return NULL; + } } - return D3DPRESENT_INTERVAL_DEFAULT; -} - -IDirect3DDevice9 *Display::getDevice() -{ return mDevice; } @@ -487,4 +533,127 @@ bool Display::getCompressedTextureSupport() 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; } +} \ No newline at end of file diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Display.h b/Source/ThirdParty/ANGLE/src/libEGL/Display.h index bd33012..4b74e1e 100644 --- a/Source/ThirdParty/ANGLE/src/libEGL/Display.h +++ b/Source/ThirdParty/ANGLE/src/libEGL/Display.h @@ -54,17 +54,25 @@ class Display bool isValidSurface(egl::Surface *surface); bool hasExistingWindowSurface(HWND window); - void setSwapInterval(GLint interval); - DWORD getPresentInterval(); - static DWORD convertInterval(GLint interval); + EGLint getMinSwapInterval(); + EGLint getMaxSwapInterval(); virtual IDirect3DDevice9 *getDevice(); virtual D3DCAPS9 getDeviceCaps(); 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 D3DPOOL getBufferPool(DWORD usage) const; private: DISALLOW_COPY_AND_ASSIGN(Display); + + D3DPRESENT_PARAMETERS getDefaultPresentParameters(); + const HDC mDc; HMODULE mD3d9Module; @@ -78,11 +86,9 @@ class Display HWND mDeviceWindow; bool mSceneStarted; - GLint mSwapInterval; EGLint mMaxSwapInterval; EGLint mMinSwapInterval; - DWORD mPresentInterval; - + typedef std::set SurfaceSet; SurfaceSet mSurfaceSet; @@ -92,6 +98,7 @@ class Display ContextSet mContextSet; bool createDevice(); + bool resetDevice(); }; } diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp b/Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp index a5638d4..2736a7f 100644 --- a/Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp +++ b/Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp @@ -8,6 +8,8 @@ // 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 + #include "libEGL/Surface.h" #include "common/debug.h" @@ -23,7 +25,6 @@ Surface::Surface(Display *display, const Config *config, HWND window) mSwapChain = NULL; mDepthStencil = NULL; mBackBuffer = NULL; - mRenderTarget = NULL; mFlipTexture = NULL; mFlipState = NULL; mPreFlipState = NULL; @@ -31,52 +32,86 @@ Surface::Surface(Display *display, const Config *config, HWND window) 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(); resetSwapChain(); } Surface::~Surface() { + unsubclassWindow(); + release(); +} + +void Surface::release() +{ if (mSwapChain) { mSwapChain->Release(); + mSwapChain = NULL; } if (mBackBuffer) { mBackBuffer->Release(); - } - - if (mRenderTarget) - { - mRenderTarget->Release(); + mBackBuffer = NULL; } if (mDepthStencil) { mDepthStencil->Release(); + mDepthStencil = NULL; } if (mFlipTexture) { mFlipTexture->Release(); + mFlipTexture = NULL; } if (mFlipState) { mFlipState->Release(); + mFlipState = NULL; } if (mPreFlipState) { mPreFlipState->Release(); + mPreFlipState = NULL; } } void Surface::resetSwapChain() { + RECT windowRect; + if (!GetClientRect(getWindowHandle(), &windowRect)) + { + ASSERT(false); + + ERR("Could not retrieve the window dimensions"); + return; + } + + resetSwapChain(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top); +} + +void Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) +{ IDirect3DDevice9 *device = mDisplay->getDevice(); + if (device == NULL) + { + return; + } + + // 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}; presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat; @@ -87,96 +122,57 @@ void Surface::resetSwapChain() presentParameters.hDeviceWindow = getWindowHandle(); presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented - presentParameters.PresentationInterval = Display::convertInterval(mConfig->mMinSwapInterval); + presentParameters.PresentationInterval = mPresentInterval; presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; presentParameters.Windowed = TRUE; + presentParameters.BackBufferWidth = backbufferWidth; + presentParameters.BackBufferHeight = backbufferHeight; - RECT windowRect; - if (!GetClientRect(getWindowHandle(), &windowRect)) - { - ASSERT(false); - return; - } - - presentParameters.BackBufferWidth = windowRect.right - windowRect.left; - presentParameters.BackBufferHeight = windowRect.bottom - windowRect.top; - - IDirect3DSwapChain9 *swapChain = NULL; - HRESULT result = device->CreateAdditionalSwapChain(&presentParameters, &swapChain); + HRESULT result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain); if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); ERR("Could not create additional swap chains: %08lX", result); + release(); return error(EGL_BAD_ALLOC); } - IDirect3DSurface9 *depthStencilSurface = NULL; result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType, - presentParameters.MultiSampleQuality, FALSE, &depthStencilSurface, NULL); + presentParameters.MultiSampleQuality, FALSE, &mDepthStencil, NULL); if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - swapChain->Release(); - ERR("Could not create depthstencil surface for new swap chain: %08lX", result); - return error(EGL_BAD_ALLOC); - } - - IDirect3DSurface9 *renderTarget = NULL; - result = device->CreateRenderTarget(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, presentParameters.BackBufferFormat, - presentParameters.MultiSampleType, presentParameters.MultiSampleQuality, FALSE, &renderTarget, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - - swapChain->Release(); - depthStencilSurface->Release(); - - ERR("Could not create render target surface for new swap chain: %08lX", result); + release(); return error(EGL_BAD_ALLOC); } ASSERT(SUCCEEDED(result)); - IDirect3DTexture9 *flipTexture = NULL; result = device->CreateTexture(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET, - presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &flipTexture, NULL); + presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &mFlipTexture, NULL); if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - swapChain->Release(); - depthStencilSurface->Release(); - renderTarget->Release(); - ERR("Could not create flip texture for new swap chain: %08lX", result); + release(); return error(EGL_BAD_ALLOC); } - IDirect3DSurface9 *backBuffer = NULL; - swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backBuffer); - - if (mSwapChain) mSwapChain->Release(); - if (mDepthStencil) mDepthStencil->Release(); - if (mBackBuffer) mBackBuffer->Release(); - if (mRenderTarget) mRenderTarget->Release(); - if (mFlipTexture) mFlipTexture->Release(); - + mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); mWidth = presentParameters.BackBufferWidth; mHeight = presentParameters.BackBufferHeight; - mSwapChain = swapChain; - mDepthStencil = depthStencilSurface; - mBackBuffer = backBuffer; - mRenderTarget = renderTarget; - mFlipTexture = flipTexture; + mPresentIntervalDirty = false; + + InvalidateRect(mWindow, NULL, FALSE); // The flip state block recorded mFlipTexture so it is now invalid. releaseRecordedState(device); @@ -199,6 +195,7 @@ void Surface::writeRecordableFlipState(IDirect3DDevice9 *device) device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); + device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); device->SetPixelShader(NULL); device->SetVertexShader(NULL); @@ -206,7 +203,7 @@ void Surface::writeRecordableFlipState(IDirect3DDevice9 *device) device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - device->SetTexture(0, NULL); // The actual texture will change after resizing. But the pre-flip state block must save/restore the texture. + device->SetTexture(0, NULL); // The actual texture will change after resizing. But the pre-flip state block must save/restore the texture. device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE); @@ -214,7 +211,10 @@ void Surface::writeRecordableFlipState(IDirect3DDevice9 *device) device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); - device->SetStreamSourceFreq(0, 1); // DrawPrimitiveUP only cares about stream 0, not the rest. + RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle + device->SetScissorRect(&scissorRect); + D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f}; + device->SetViewport(&viewport); } void Surface::applyFlipState(IDirect3DDevice9 *device) @@ -275,8 +275,6 @@ void Surface::applyFlipState(IDirect3DDevice9 *device) void Surface::restoreState(IDirect3DDevice9 *device) { - mPreFlipState->Apply(); - device->SetRenderTarget(0, mPreFlipBackBuffer); device->SetDepthStencilSurface(mPreFlipDepthStencil); @@ -291,6 +289,8 @@ void Surface::restoreState(IDirect3DDevice9 *device) mPreFlipDepthStencil->Release(); mPreFlipDepthStencil = NULL; } + + mPreFlipState->Apply(); } // On the next flip, this will cause the state to be recorded from scratch. @@ -309,8 +309,58 @@ void Surface::releaseRecordedState(IDirect3DDevice9 *device) mPreFlipState = NULL; } } +#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(GetProp(hwnd, kSurfaceProperty)); + if(surf) { + surf->checkForOutOfDateSwapChain(); + } + } + WNDPROC prevWndFunc = reinterpret_cast(GetProp(hwnd, kParentWndProc)); + return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam); +} -bool Surface::checkForWindowResize() +void Surface::subclassWindow() +{ + SetLastError(0); + LONG oldWndProc = SetWindowLong(mWindow, GWL_WNDPROC, reinterpret_cast(SurfaceWindowProc)); + if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS) { + mWindowSubclassed = false; + return; + } + + SetProp(mWindow, kSurfaceProperty, reinterpret_cast(this)); + SetProp(mWindow, kParentWndProc, reinterpret_cast(oldWndProc)); + mWindowSubclassed = true; +} + +void Surface::unsubclassWindow() +{ + if(!mWindowSubclassed) + return; + + // un-subclass + LONG parentWndFunc = reinterpret_cast(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(SurfaceWindowProc)); + } + + RemoveProp(mWindow, kSurfaceProperty); + RemoveProp(mWindow, kParentWndProc); + mWindowSubclassed = false; +} + +bool Surface::checkForOutOfDateSwapChain() { RECT client; if (!GetClientRect(getWindowHandle(), &client)) @@ -319,10 +369,14 @@ bool Surface::checkForWindowResize() return false; } - if (getWidth() != client.right - client.left || getHeight() != client.bottom - client.top) - { - resetSwapChain(); + // 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(getCurrentDrawSurface()) == this) { glMakeCurrent(glGetCurrentContext(), static_cast(getCurrentDisplay()), this); @@ -330,57 +384,51 @@ bool Surface::checkForWindowResize() return true; } - return false; } -bool Surface::swap() +DWORD Surface::convertInterval(EGLint interval) { - if (mSwapChain) + switch(interval) { - IDirect3DTexture9 *flipTexture = mFlipTexture; - flipTexture->AddRef(); - - IDirect3DSurface9 *renderTarget = mRenderTarget; - renderTarget->AddRef(); + 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(); + } - EGLint oldWidth = mWidth; - EGLint oldHeight = mHeight; + return D3DPRESENT_INTERVAL_DEFAULT; +} - checkForWindowResize(); +bool Surface::swap() +{ + if (mSwapChain) + { IDirect3DDevice9 *device = mDisplay->getDevice(); - IDirect3DSurface9 *textureSurface; - flipTexture->GetSurfaceLevel(0, &textureSurface); - - mDisplay->endScene(); - device->StretchRect(renderTarget, NULL, textureSurface, NULL, D3DTEXF_NONE); - renderTarget->Release(); - applyFlipState(device); - device->SetTexture(0, flipTexture); - - float xscale = (float)mWidth / oldWidth; - float yscale = (float)mHeight / oldHeight; + device->SetTexture(0, mFlipTexture); // Render the texture upside down into the back buffer - // Texcoords are chosen to pin a potentially resized image into the upper-left corner without scaling. - float quad[4][6] = {{ 0 - 0.5f, 0 - 0.5f, 0.0f, 1.0f, 0.0f, 1.0f }, - {mWidth - 0.5f, 0 - 0.5f, 0.0f, 1.0f, xscale, 1.0f }, - {mWidth - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, xscale, 1.0f-yscale}, - { 0 - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, 0.0f, 1.0f-yscale}}; // x, y, z, rhw, u, v + // Texcoords are chosen to flip the renderTarget about its Y axis. + float w = static_cast(getWidth()); + float h = static_cast(getHeight()); + float quad[4][6] = {{0 - 0.5f, 0 - 0.5f, 0.0f, 1.0f, 0.0f, 1.0f}, + {w - 0.5f, 0 - 0.5f, 0.0f, 1.0f, 1.0f, 1.0f}, + {w - 0.5f, h - 0.5f, 0.0f, 1.0f, 1.0f, 0.0f}, + {0 - 0.5f, h - 0.5f, 0.0f, 1.0f, 0.0f, 0.0f}}; // x, y, z, rhw, u, v mDisplay->startScene(); device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); - flipTexture->Release(); - textureSurface->Release(); - restoreState(device); mDisplay->endScene(); - HRESULT result = mSwapChain->Present(NULL, NULL, NULL, NULL, mDisplay->getPresentInterval()); + + HRESULT result = mSwapChain->Present(NULL, NULL, NULL, NULL, 0); if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) { @@ -394,6 +442,7 @@ bool Surface::swap() ASSERT(SUCCEEDED(result)); + checkForOutOfDateSwapChain(); } return true; @@ -411,12 +460,14 @@ EGLint Surface::getHeight() const IDirect3DSurface9 *Surface::getRenderTarget() { - if (mRenderTarget) + IDirect3DSurface9 *textureSurface = NULL; + + if (mFlipTexture) { - mRenderTarget->AddRef(); + mFlipTexture->GetSurfaceLevel(0, &textureSurface); } - return mRenderTarget; + return textureSurface; } IDirect3DSurface9 *Surface::getDepthStencil() @@ -428,4 +479,19 @@ IDirect3DSurface9 *Surface::getDepthStencil() return mDepthStencil; } + +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; +} } diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Surface.h b/Source/ThirdParty/ANGLE/src/libEGL/Surface.h index 5bc912c..422d3d5 100644 --- a/Source/ThirdParty/ANGLE/src/libEGL/Surface.h +++ b/Source/ThirdParty/ANGLE/src/libEGL/Surface.h @@ -29,6 +29,9 @@ class Surface ~Surface(); + void release(); + void resetSwapChain(); + HWND getWindowHandle(); bool swap(); @@ -38,18 +41,22 @@ class Surface virtual IDirect3DSurface9 *getRenderTarget(); virtual IDirect3DSurface9 *getDepthStencil(); - private: + void setSwapInterval(EGLint interval); + bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update + +private: DISALLOW_COPY_AND_ASSIGN(Surface); Display *const mDisplay; IDirect3DSwapChain9 *mSwapChain; IDirect3DSurface9 *mBackBuffer; - IDirect3DSurface9 *mRenderTarget; IDirect3DSurface9 *mDepthStencil; IDirect3DTexture9 *mFlipTexture; - void resetSwapChain(); - bool checkForWindowResize(); + void subclassWindow(); + void unsubclassWindow(); + void resetSwapChain(int backbufferWidth, int backbufferHeight); + static DWORD convertInterval(EGLint interval); void applyFlipState(IDirect3DDevice9 *device); void restoreState(IDirect3DDevice9 *device); @@ -61,6 +68,7 @@ class Surface IDirect3DSurface9 *mPreFlipDepthStencil; 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 @@ -77,6 +85,9 @@ class Surface // EGLenum textureTarget; // 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; }; } diff --git a/Source/ThirdParty/ANGLE/src/libEGL/libEGL.cpp b/Source/ThirdParty/ANGLE/src/libEGL/libEGL.cpp index 5ceb6ef..8dfe6e5 100644 --- a/Source/ThirdParty/ANGLE/src/libEGL/libEGL.cpp +++ b/Source/ThirdParty/ANGLE/src/libEGL/libEGL.cpp @@ -360,6 +360,8 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG default: return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); } + + attrib_list += 2; } } @@ -746,7 +748,14 @@ EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval) return EGL_FALSE; } - display->setSwapInterval(interval); + egl::Surface *draw_surface = static_cast(egl::getCurrentDrawSurface()); + + if (draw_surface == NULL) + { + return error(EGL_BAD_SURFACE, EGL_FALSE); + } + + draw_surface->setSwapInterval(interval); return success(EGL_TRUE); } @@ -765,6 +774,28 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte 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(dpy); if (!validate(display, config)) @@ -825,7 +856,7 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface gl::Context *context = static_cast(ctx); IDirect3DDevice9 *device = display->getDevice(); - if (!device || device->TestCooperativeLevel() != D3D_OK) + if (!device || FAILED(device->TestCooperativeLevel())) { return error(EGL_CONTEXT_LOST, EGL_FALSE); } diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.cpp index 00c878f..43ed8a0 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.cpp +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.cpp @@ -382,6 +382,11 @@ bool Blit::setFormatConvertShaders(GLenum destFormat) IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect) { + if (!surface) + { + return NULL; + } + egl::Display *display = getDisplay(); IDirect3DDevice9 *device = getDevice(); @@ -408,14 +413,8 @@ IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); } - RECT d3dSourceRect; - d3dSourceRect.left = sourceRect.left; - d3dSourceRect.right = sourceRect.right; - d3dSourceRect.top = sourceRect.top; - d3dSourceRect.bottom = sourceRect.bottom; - display->endScene(); - result = device->StretchRect(surface, &d3dSourceRect, textureSurface, NULL, D3DTEXF_NONE); + result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE); textureSurface->Release(); @@ -467,10 +466,8 @@ void Blit::setCommonBlitState() device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - for (int i = 0; i < MAX_VERTEX_ATTRIBS+1; i++) - { - device->SetStreamSourceFreq(i, 1); - } + 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() diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.cpp index 43993e7..17cea6c 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.cpp +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.cpp @@ -10,6 +10,10 @@ #include "libGLESv2/Buffer.h" +#include "libGLESv2/main.h" +#include "libGLESv2/geometry/VertexDataManager.h" +#include "libGLESv2/geometry/IndexDataManager.h" + namespace gl { @@ -18,11 +22,16 @@ Buffer::Buffer(GLuint id) : RefCountObject(id) mContents = NULL; mSize = 0; mUsage = GL_DYNAMIC_DRAW; + + mVertexBuffer = NULL; + mIndexBuffer = NULL; } Buffer::~Buffer() { delete[] mContents; + delete mVertexBuffer; + delete mIndexBuffer; } void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) @@ -46,11 +55,52 @@ void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) mSize = size; mUsage = usage; + + invalidateStaticData(); + + if (usage == GL_STATIC_DRAW) + { + mVertexBuffer = new StaticVertexBuffer(getDevice()); + mIndexBuffer = new StaticIndexBuffer(getDevice()); + } } void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) { memcpy(mContents + offset, data, size); + + if ((mVertexBuffer && mVertexBuffer->size() != 0) || (mIndexBuffer && mIndexBuffer->size() != 0)) + { + invalidateStaticData(); + + if (mUsage == GL_STATIC_DRAW) + { + // If applications update the buffer data after it has already been used in a draw call, + // it most likely isn't used as a static buffer so we should fall back to streaming usage + // for best performance. So ignore the usage hint and don't create new static buffers. + // mVertexBuffer = new StaticVertexBuffer(getDevice()); + // mIndexBuffer = new StaticIndexBuffer(getDevice()); + } + } +} + +StaticVertexBuffer *Buffer::getVertexBuffer() +{ + return mVertexBuffer; +} + +StaticIndexBuffer *Buffer::getIndexBuffer() +{ + return mIndexBuffer; +} + +void Buffer::invalidateStaticData() +{ + delete mVertexBuffer; + mVertexBuffer = NULL; + + delete mIndexBuffer; + mIndexBuffer = NULL; } } diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.h index 5611cc9..c2ed60f 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.h +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.h @@ -22,6 +22,8 @@ namespace gl { +class StaticVertexBuffer; +class StaticIndexBuffer; class Buffer : public RefCountObject { @@ -37,12 +39,19 @@ class Buffer : public RefCountObject size_t size() const { return mSize; } GLenum usage() const { return mUsage; } + StaticVertexBuffer *getVertexBuffer(); + StaticIndexBuffer *getIndexBuffer(); + void invalidateStaticData(); + private: DISALLOW_COPY_AND_ASSIGN(Buffer); GLubyte *mContents; size_t mSize; GLenum mUsage; + + StaticVertexBuffer *mVertexBuffer; + StaticIndexBuffer *mIndexBuffer; }; } diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp index 48ef8fc..9be59c4 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp @@ -19,15 +19,14 @@ #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/geometry/backend.h" #include "libGLESv2/geometry/VertexDataManager.h" #include "libGLESv2/geometry/IndexDataManager.h" -#include "libGLESv2/geometry/dx9.h" #undef near #undef far @@ -83,6 +82,7 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext) mState.scissorTest = false; mState.dither = true; mState.generateMipmapHint = GL_DONT_CARE; + mState.fragmentShaderDerivativeHint = GL_DONT_CARE; mState.lineWidth = 1.0f; @@ -120,11 +120,8 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext) // In order that access to these initial textures not be lost, they are treated as texture // objects all of whose names are 0. - mTexture2DZero = new Texture2D(0); - mTextureCubeMapZero = new TextureCubeMap(0); - - mColorbufferZero = NULL; - mDepthStencilbufferZero = NULL; + mTexture2DZero.set(new Texture2D(0)); + mTextureCubeMapZero.set(new TextureCubeMap(0)); mState.activeSampler = 0; bindArrayBuffer(0); @@ -135,17 +132,11 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext) bindDrawFramebuffer(0); bindRenderbuffer(0); - for (int type = 0; type < SAMPLER_TYPE_COUNT; type++) - { - mIncompleteTextures[type] = NULL; - } - mState.currentProgram = 0; mState.packAlignment = 4; mState.unpackAlignment = 4; - mBufferBackEnd = NULL; mVertexDataManager = NULL; mIndexDataManager = NULL; mBlit = NULL; @@ -158,6 +149,8 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext) mHasBeenCurrent = false; + mSupportsCompressedTextures = false; + mSupportsEventQueries = false; mMaxSupportedSamples = 0; mMaskedClearSavedState = NULL; markAllStateDirty(); @@ -180,6 +173,11 @@ Context::~Context() deleteFramebuffer(mFramebufferMap.begin()->first); } + while (!mFenceMap.empty()) + { + deleteFence(mFenceMap.begin()->first); + } + while (!mMultiSampleSupport.empty()) { delete [] mMultiSampleSupport.begin()->second; @@ -196,7 +194,7 @@ Context::~Context() for (int type = 0; type < SAMPLER_TYPE_COUNT; type++) { - delete mIncompleteTextures[type]; + mIncompleteTextures[type].set(NULL); } for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) @@ -206,14 +204,11 @@ Context::~Context() mState.arrayBuffer.set(NULL); mState.elementArrayBuffer.set(NULL); - mState.texture2D.set(NULL); - mState.textureCubeMap.set(NULL); mState.renderbuffer.set(NULL); - delete mTexture2DZero; - delete mTextureCubeMapZero; + mTexture2DZero.set(NULL); + mTextureCubeMapZero.set(NULL); - delete mBufferBackEnd; delete mVertexDataManager; delete mIndexDataManager; delete mBlit; @@ -234,11 +229,20 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface) { mDeviceCaps = display->getDeviceCaps(); - mBufferBackEnd = new Dx9BackEnd(this, device); - mVertexDataManager = new VertexDataManager(this, mBufferBackEnd); - mIndexDataManager = new IndexDataManager(this, mBufferBackEnd); + mVertexDataManager = new VertexDataManager(this, device); + mIndexDataManager = new IndexDataManager(this, device); mBlit = new Blit(this); + mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0); + + 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, @@ -265,7 +269,14 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface) 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(); @@ -292,15 +303,16 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface) setFramebufferZero(framebufferZero); - defaultRenderTarget->Release(); + if (defaultRenderTarget) + { + defaultRenderTarget->Release(); + } if (depthStencil) { depthStencil->Release(); } - mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0); - markAllStateDirty(); } @@ -309,6 +321,8 @@ void Context::markAllStateDirty() { mAppliedRenderTargetSerial = 0; mAppliedDepthbufferSerial = 0; + mAppliedStencilbufferSerial = 0; + mDepthStencilInitialized = false; mAppliedProgram = 0; mClearStateDirty = true; @@ -322,11 +336,6 @@ void Context::markAllStateDirty() mSampleStateDirty = true; mDitherStateDirty = true; mFrontFaceDirty = true; - - if (mBufferBackEnd != NULL) - { - mBufferBackEnd->invalidate(); - } } void Context::setClearColor(float red, float green, float blue, float alpha) @@ -650,6 +659,14 @@ 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; @@ -718,12 +735,12 @@ GLuint Context::getArrayBufferHandle() const return mState.arrayBuffer.id(); } -void Context::setVertexAttribEnabled(unsigned int attribNum, bool enabled) +void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) { - mState.vertexAttribute[attribNum].mEnabled = enabled; + mState.vertexAttribute[attribNum].mArrayEnabled = enabled; } -const AttributeState &Context::getVertexAttribState(unsigned int attribNum) +const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum) { return mState.vertexAttribute[attribNum]; } @@ -744,8 +761,7 @@ const void *Context::getVertexAttribPointer(unsigned int attribNum) const return mState.vertexAttribute[attribNum].mPointer; } -// returns entire set of attributes as a block -const AttributeState *Context::getVertexAttribBlock() +const VertexAttributeArray &Context::getVertexAttributes() { return mState.vertexAttribute; } @@ -810,6 +826,20 @@ GLuint Context::createFramebuffer() return handle; } +GLuint Context::createFence() +{ + unsigned int handle = 0; + + while (mFenceMap.find(handle) != mFenceMap.end()) + { + handle++; + } + + mFenceMap[handle] = new Fence; + + return handle; +} + void Context::deleteBuffer(GLuint buffer) { if (mResourceManager->getBuffer(buffer)) @@ -863,6 +893,17 @@ void Context::deleteFramebuffer(GLuint framebuffer) } } +void Context::deleteFence(GLuint fence) +{ + FenceMap::iterator fenceObject = mFenceMap.find(fence); + + if (fenceObject != mFenceMap.end()) + { + delete fenceObject->second; + mFenceMap.erase(fenceObject); + } +} + Buffer *Context::getBuffer(GLuint handle) { return mResourceManager->getBuffer(handle); @@ -916,18 +957,14 @@ void Context::bindTexture2D(GLuint texture) { mResourceManager->checkTextureAllocation(texture, SAMPLER_2D); - mState.texture2D.set(getTexture(texture)); - - mState.samplerTexture[SAMPLER_2D][mState.activeSampler].set(mState.texture2D.get()); + mState.samplerTexture[SAMPLER_2D][mState.activeSampler].set(getTexture(texture)); } void Context::bindTextureCubeMap(GLuint texture) { mResourceManager->checkTextureAllocation(texture, SAMPLER_CUBE); - mState.textureCubeMap.set(getTexture(texture)); - - mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].set(mState.textureCubeMap.get()); + mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].set(getTexture(texture)); } void Context::bindReadFramebuffer(GLuint framebuffer) @@ -1005,6 +1042,20 @@ Framebuffer *Context::getFramebuffer(unsigned int handle) } } +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(); @@ -1022,35 +1073,25 @@ Program *Context::getCurrentProgram() Texture2D *Context::getTexture2D() { - if (mState.texture2D.id() == 0) // Special case: 0 refers to different initial textures based on the target - { - return mTexture2DZero; - } - - return static_cast(mState.texture2D.get()); + return static_cast(getSamplerTexture(mState.activeSampler, SAMPLER_2D)); } TextureCubeMap *Context::getTextureCubeMap() { - if (mState.textureCubeMap.id() == 0) // Special case: 0 refers to different initial textures based on the target - { - return mTextureCubeMapZero; - } - - return static_cast(mState.textureCubeMap.get()); + return static_cast(getSamplerTexture(mState.activeSampler, SAMPLER_CUBE)); } Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type) { GLuint texid = mState.samplerTexture[type][sampler].id(); - if (texid == 0) + if (texid == 0) // Special case: 0 refers to different initial textures based on the target { switch (type) { default: UNREACHABLE(); - case SAMPLER_2D: return mTexture2DZero; - case SAMPLER_CUBE: return mTextureCubeMapZero; + case SAMPLER_2D: return mTexture2DZero.get(); + case SAMPLER_CUBE: return mTextureCubeMapZero.get(); } } @@ -1070,15 +1111,15 @@ bool Context::getBooleanv(GLenum pname, GLboolean *params) params[2] = mState.colorMaskBlue; params[3] = mState.colorMaskAlpha; break; - case GL_CULL_FACE: *params = mState.cullFace; - case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill; - case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage; - case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; - case GL_SCISSOR_TEST: *params = mState.scissorTest; - case GL_STENCIL_TEST: *params = mState.stencilTest; - case GL_DEPTH_TEST: *params = mState.depthTest; - case GL_BLEND: *params = mState.blend; - case GL_DITHER: *params = mState.dither; + 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; } @@ -1141,24 +1182,25 @@ bool Context::getIntegerv(GLenum pname, GLint *params) { case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break; case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break; - case GL_MAX_VARYING_VECTORS: *params = gl::MAX_VARYING_VECTORS; break; + case GL_MAX_VARYING_VECTORS: *params = getMaximumVaryingVectors(); break; case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break; case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break; case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break; - case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break; - case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break; + case GL_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_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; @@ -1183,8 +1225,8 @@ bool Context::getIntegerv(GLenum pname, GLint *params) case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break; case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break; case GL_SUBPIXEL_BITS: *params = 4; break; - case GL_MAX_TEXTURE_SIZE: *params = gl::MAX_TEXTURE_SIZE; break; - case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; break; + case GL_MAX_TEXTURE_SIZE: *params = getMaximumTextureDimension(); break; + case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = getMaximumCubeTextureDimension(); break; case GL_NUM_COMPRESSED_TEXTURE_FORMATS: { if (supportsCompressedTextures()) @@ -1246,7 +1288,7 @@ bool Context::getIntegerv(GLenum pname, GLint *params) case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break; case GL_MAX_VIEWPORT_DIMS: { - int maxDimension = std::max((int)gl::MAX_RENDERBUFFER_SIZE, (int)gl::MAX_TEXTURE_SIZE); + int maxDimension = std::max(getMaximumRenderbufferDimension(), getMaximumTextureDimension()); params[0] = maxDimension; params[1] = maxDimension; } @@ -1392,6 +1434,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu 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: @@ -1535,6 +1578,12 @@ bool Context::applyRenderTarget(bool ignoreViewport) } IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget(); + + if (!renderTarget) + { + return false; // Context must be lost + } + IDirect3DSurface9 *depthStencil = NULL; unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial(); @@ -1550,26 +1599,43 @@ bool Context::applyRenderTarget(bool ignoreViewport) 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) + 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; @@ -1585,8 +1651,8 @@ bool Context::applyRenderTarget(bool ignoreViewport) viewport.Y = std::max(mState.viewportY, 0); viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X); viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y); - viewport.MinZ = clamp01(mState.zNear); - viewport.MaxZ = clamp01(mState.zFar); + viewport.MinZ = zNear; + viewport.MaxZ = zFar; } if (viewport.Width <= 0 || viewport.Height <= 0) @@ -1623,27 +1689,21 @@ bool Context::applyRenderTarget(bool ignoreViewport) GLint halfPixelSize = programObject->getDxHalfPixelSizeLocation(); GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height}; - programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy); + programObject->setUniform2fv(halfPixelSize, 1, xy); - GLint window = programObject->getDxViewportLocation(); + 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(window, 1, (GLfloat*)&whxy); + programObject->setUniform4fv(viewport, 1, whxy); GLint depth = programObject->getDxDepthLocation(); - GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f}; - programObject->setUniform2fv(depth, 1, (GLfloat*)&dz); + GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f}; + programObject->setUniform2fv(depth, 1, dz); - GLint near = programObject->getDepthRangeNearLocation(); - programObject->setUniform1fv(near, 1, &mState.zNear); - - GLint far = programObject->getDepthRangeFarLocation(); - programObject->setUniform1fv(far, 1, &mState.zFar); - - GLint diff = programObject->getDepthRangeDiffLocation(); - GLfloat zDiff = mState.zFar - mState.zNear; - programObject->setUniform1fv(diff, 1, &zDiff); + GLint depthRange = programObject->getDxDepthRangeLocation(); + GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear}; + programObject->setUniform3fv(depthRange, 1, nearFarDiff); } return true; @@ -1830,39 +1890,46 @@ void Context::applyState(GLenum drawMode) mPolygonOffsetStateDirty = false; } - if (framebufferObject->isMultisample() && mSampleStateDirty) + if (mSampleStateDirty) { - if (mState.sampleAlphaToCoverage) + if (framebufferObject->isMultisample()) { - FIXME("Sample alpha to coverage is unimplemented."); - } + if (mState.sampleAlphaToCoverage) + { + FIXME("Sample alpha to coverage is unimplemented."); + } - if (mState.sampleCoverage) - { device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); - unsigned int mask = 0; - if (mState.sampleCoverageValue != 0) + if (mState.sampleCoverage) { - float threshold = 0.5f; - - for (int i = 0; i < framebufferObject->getSamples(); ++i) + unsigned int mask = 0; + if (mState.sampleCoverageValue != 0) { - mask <<= 1; + float threshold = 0.5f; - if ((i + 1) * mState.sampleCoverageValue >= threshold) + for (int i = 0; i < framebufferObject->getSamples(); ++i) { - threshold += 1.0f; - mask |= 1; + mask <<= 1; + + if ((i + 1) * mState.sampleCoverageValue >= threshold) + { + threshold += 1.0f; + mask |= 1; + } } } + + if (mState.sampleCoverageInvert) + { + mask = ~mask; + } + + device->SetRenderState(D3DRS_MULTISAMPLEMASK, mask); } - - if (mState.sampleCoverageInvert) + else { - mask = ~mask; + device->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); } - - device->SetRenderState(D3DRS_MULTISAMPLEMASK, mask); } else { @@ -1887,18 +1954,18 @@ void Context::lookupAttributeMapping(TranslatedAttribute *attributes) { for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) { - if (attributes[i].enabled) + if (attributes[i].active) { attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i); } } } -GLenum Context::applyVertexBuffer(GLenum mode, GLint first, GLsizei count, bool *useIndexing, TranslatedIndexData *indexInfo) +GLenum Context::applyVertexBuffer(GLint first, GLsizei count) { TranslatedAttribute translated[MAX_VERTEX_ATTRIBS]; - GLenum err = mVertexDataManager->preRenderValidate(first, count, translated); + GLenum err = mVertexDataManager->prepareVertexData(first, count, translated); if (err != GL_NO_ERROR) { return err; @@ -1906,53 +1973,20 @@ GLenum Context::applyVertexBuffer(GLenum mode, GLint first, GLsizei count, bool lookupAttributeMapping(translated); - mBufferBackEnd->setupAttributesPreDraw(translated); - - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if (translated[i].enabled && translated[i].nonArray) - { - err = mIndexDataManager->preRenderValidateUnindexed(mode, count, indexInfo); - if (err != GL_NO_ERROR) - { - return err; - } + mVertexDataManager->setupAttributes(translated); - mBufferBackEnd->setupIndicesPreDraw(*indexInfo); - - *useIndexing = true; - return GL_NO_ERROR; - } - } - - *useIndexing = false; return GL_NO_ERROR; } -GLenum Context::applyVertexBuffer(const TranslatedIndexData &indexInfo) -{ - TranslatedAttribute translated[MAX_VERTEX_ATTRIBS]; - - GLenum err = mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated); - - if (err == GL_NO_ERROR) - { - lookupAttributeMapping(translated); - - mBufferBackEnd->setupAttributesPreDraw(translated); - } - - return err; -} - // Applies the indices and element array bindings to the Direct3D 9 device GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) { - GLenum err = mIndexDataManager->preRenderValidate(mode, type, count, mState.elementArrayBuffer.get(), indices, indexInfo); + IDirect3DDevice9 *device = getDevice(); + GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer.get(), indices, indexInfo); if (err == GL_NO_ERROR) { - mBufferBackEnd->setupIndicesPreDraw(*indexInfo); + device->SetIndices(indexInfo->indexBuffer); } return err; @@ -2048,6 +2082,12 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum } IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget(); + + if (!renderTarget) + { + return; // Context must be lost, return silently + } + IDirect3DDevice9 *device = getDevice(); D3DSURFACE_DESC desc; @@ -2141,16 +2181,6 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum r = (rgb & 0xF800) * (1.0f / 0xF800); } break; - case D3DFMT_X1R5G5B5: - { - unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch); - - a = 1.0f; - b = (xrgb & 0x001F) * (1.0f / 0x001F); - g = (xrgb & 0x03E0) * (1.0f / 0x03E0); - r = (xrgb & 0x7C00) * (1.0f / 0x7C00); - } - break; case D3DFMT_A1R5G5B5: { unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch); @@ -2191,6 +2221,28 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum 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 * lock.Pitch) + 0); + g = *((float*)(source + 16 * i + j * lock.Pitch) + 1); + b = *((float*)(source + 16 * i + j * lock.Pitch) + 2); + a = *((float*)(source + 16 * i + j * lock.Pitch) + 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 * lock.Pitch), 4); + + a = abgr[3]; + b = abgr[2]; + g = abgr[1]; + r = abgr[0]; + } + break; default: UNIMPLEMENTED(); // FIXME UNREACHABLE(); @@ -2314,6 +2366,12 @@ void Context::clear(GLbitfield mask) 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); @@ -2346,6 +2404,11 @@ void Context::clear(GLbitfield mask) IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget(); + if (!renderTarget) + { + return; // Context must be lost, return silently + } + D3DSURFACE_DESC desc; renderTarget->GetDesc(&desc); @@ -2381,7 +2444,7 @@ void Context::clear(GLbitfield mask) device->SetPixelShader(NULL); device->SetVertexShader(NULL); device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); - device->SetStreamSourceFreq(0, 1); + device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); hr = device->EndStateBlock(&mMaskedClearSavedState); ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); @@ -2436,7 +2499,7 @@ void Context::clear(GLbitfield mask) device->SetPixelShader(NULL); device->SetVertexShader(NULL); device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); - device->SetStreamSourceFreq(0, 1); + device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); struct Vertex { @@ -2517,9 +2580,7 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count) applyState(mode); - TranslatedIndexData indexInfo; - bool useIndexing; - GLenum err = applyVertexBuffer(mode, first, count, &useIndexing, &indexInfo); + GLenum err = applyVertexBuffer(first, count); if (err != GL_NO_ERROR) { return error(err); @@ -2536,18 +2597,17 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count) if (!cullSkipsDraw(mode)) { display->startScene(); - if (useIndexing) - { - device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/indexInfo.indexSize, primitiveCount); - } - else + + device->DrawPrimitive(primitiveType, 0, primitiveCount); + + if (mode == GL_LINE_LOOP) // Draw the last segment separately { - device->DrawPrimitive(primitiveType, 0, primitiveCount); + drawClosingLine(first, first + count - 1); } } } -void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) +void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) { if (!mState.currentProgram) { @@ -2586,7 +2646,8 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* return error(err); } - err = applyVertexBuffer(indexInfo); + GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; + err = applyVertexBuffer(indexInfo.minIndex, vertexCount); if (err != GL_NO_ERROR) { return error(err); @@ -2603,7 +2664,13 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* if (!cullSkipsDraw(mode)) { display->startScene(); - device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/indexInfo.indexSize, primitiveCount); + + 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); + } } } @@ -2631,7 +2698,6 @@ void Context::finish() ASSERT(SUCCEEDED(result)); // Render something outside the render target - device->SetStreamSourceFreq(0, 1); device->SetPixelShader(NULL); device->SetVertexShader(NULL); device->SetFVF(D3DFVF_XYZRHW); @@ -2687,6 +2753,93 @@ void Context::flush() } } +void Context::drawClosingLine(unsigned int first, unsigned int last) +{ + IDirect3DDevice9 *device = getDevice(); + IDirect3DIndexBuffer9 *indexBuffer = NULL; + HRESULT result = D3DERR_INVALIDCALL; + + if (supports32bitIndices()) + { + result = device->CreateIndexBuffer(8, D3DUSAGE_WRITEONLY, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &indexBuffer, 0); + + if (SUCCEEDED(result)) + { + unsigned int *data; + result = indexBuffer->Lock(0, 0, (void**)&data, 0); + + if (SUCCEEDED(result)) + { + data[0] = last; + data[1] = first; + } + } + } + else + { + result = device->CreateIndexBuffer(4, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &indexBuffer, 0); + + if (SUCCEEDED(result)) + { + unsigned short *data; + result = indexBuffer->Lock(0, 0, (void**)&data, 0); + + if (SUCCEEDED(result)) + { + data[0] = last; + data[1] = first; + } + } + } + + if (SUCCEEDED(result)) + { + indexBuffer->Unlock(); + device->SetIndices(indexBuffer); + + device->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, 2, 0, 1); + + indexBuffer->Release(); + } + 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(indices); + indices = static_cast(indexBuffer->data()) + offset; + } + + switch (type) + { + case GL_UNSIGNED_BYTE: + first = static_cast(indices)[0]; + last = static_cast(indices)[count - 1]; + break; + case GL_UNSIGNED_SHORT: + first = static_cast(indices)[0]; + last = static_cast(indices)[count - 1]; + break; + case GL_UNSIGNED_INT: + first = static_cast(indices)[0]; + last = static_cast(indices)[count - 1]; + break; + default: UNREACHABLE(); + } + + drawClosingLine(first, last); +} + void Context::recordInvalidEnum() { mInvalidEnum = true; @@ -2759,6 +2912,16 @@ bool Context::supportsShaderModel3() const return mSupportsShaderModel3; } +int Context::getMaximumVaryingVectors() const +{ + return mSupportsShaderModel3 ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2; +} + +int Context::getMaximumFragmentUniformVectors() const +{ + return mSupportsShaderModel3 ? MAX_FRAGMENT_UNIFORM_VECTORS_SM3 : MAX_FRAGMENT_UNIFORM_VECTORS_SM2; +} + int Context::getMaxSupportedSamples() const { return mMaxSupportedSamples; @@ -2788,11 +2951,81 @@ int Context::getNearestSupportedSamples(D3DFORMAT format, int requested) const 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; +} + void Context::detachBuffer(GLuint buffer) { // [OpenGL ES 2.0.24] section 2.9 page 22: @@ -2903,7 +3136,7 @@ void Context::detachRenderbuffer(GLuint renderbuffer) Texture *Context::getIncompleteTexture(SamplerType type) { - Texture *t = mIncompleteTextures[type]; + Texture *t = mIncompleteTextures[type].get(); if (t == NULL) { @@ -2939,7 +3172,7 @@ Texture *Context::getIncompleteTexture(SamplerType type) break; } - mIncompleteTextures[type] = t; + mIncompleteTextures[type].set(t); } return t; @@ -2978,7 +3211,7 @@ void Context::setVertexAttrib(GLuint index, const GLfloat *values) mState.vertexAttribute[index].mCurrentValue[2] = values[2]; mState.vertexAttribute[index].mCurrentValue[3] = values[3]; - mVertexDataManager->dirtyCurrentValues(); + mVertexDataManager->dirtyCurrentValue(index); } void Context::initExtensionString() @@ -2988,18 +3221,44 @@ void Context::initExtensionString() 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 (mBufferBackEnd->supportIntIndices()) + if (supports32bitIndices()) { mExtensionString += "GL_OES_element_index_uint "; } @@ -3178,10 +3437,10 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 } bool partialBufferCopy = false; - if (sourceTrimmedRect.bottom - sourceTrimmedRect.top < readFramebuffer->getColorbuffer()->getHeight() || - sourceTrimmedRect.right - sourceTrimmedRect.left < readFramebuffer->getColorbuffer()->getWidth() || - destTrimmedRect.bottom - destTrimmedRect.top < drawFramebuffer->getColorbuffer()->getHeight() || - destTrimmedRect.right - destTrimmedRect.left < drawFramebuffer->getColorbuffer()->getWidth() || + 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; @@ -3189,7 +3448,11 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 if (mask & GL_COLOR_BUFFER_BIT) { - if (readFramebuffer->getColorbufferType() != drawFramebuffer->getColorbufferType() || + 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"); diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Context.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Context.h index 6bca756..2906664 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/Context.h +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Context.h @@ -12,6 +12,7 @@ #define GL_APICALL #include +#include #define EGLAPI #include #include @@ -49,19 +50,20 @@ class Stencilbuffer; class DepthStencilbuffer; class VertexDataManager; class IndexDataManager; -class BufferBackEnd; class Blit; +class Fence; enum { - MAX_VERTEX_ATTRIBS = 12, - MAX_VERTEX_UNIFORM_VECTORS = 128, - MAX_VARYING_VECTORS = 8, + 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_COMBINED_TEXTURE_IMAGE_UNITS = 16, MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0, MAX_TEXTURE_IMAGE_UNITS = 16, - MAX_FRAGMENT_UNIFORM_VECTORS = 16, - MAX_RENDERBUFFER_SIZE = 4096, // FIXME: Verify + MAX_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, @@ -83,32 +85,56 @@ struct Color }; // Helper structure describing a single vertex attribute -class AttributeState +class VertexAttribute { public: - AttributeState() - : mType(GL_FLOAT), mSize(0), mNormalized(false), mStride(0), mPointer(NULL), mEnabled(false) + VertexAttribute() : mType(GL_FLOAT), mSize(0), mNormalized(false), mStride(0), mPointer(NULL), mArrayEnabled(false) { - mCurrentValue[0] = 0; - mCurrentValue[1] = 0; - mCurrentValue[2] = 0; - mCurrentValue[3] = 1; + mCurrentValue[0] = 0.0f; + mCurrentValue[1] = 0.0f; + mCurrentValue[2] = 0.0f; + mCurrentValue[3] = 1.0f; } - // From VertexArrayPointer + 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 - const void *mPointer; + GLsizei mStride; // 0 means natural stride - BindingPointer mBoundBuffer; // Captured when VertexArrayPointer is called. + union + { + const void *mPointer; + intptr_t mOffset; + }; - bool mEnabled; // From Enable/DisableVertexAttribArray + BindingPointer mBoundBuffer; // Captured when glVertexAttribPointer is called. - float mCurrentValue[4]; // From VertexAttrib4f + 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 { @@ -157,6 +183,7 @@ struct State GLfloat lineWidth; GLenum generateMipmapHint; + GLenum fragmentShaderDerivativeHint; GLint viewportX; GLint viewportY; @@ -179,14 +206,12 @@ struct State int activeSampler; // Active texture unit selector - GL_TEXTURE0 BindingPointer arrayBuffer; BindingPointer elementArrayBuffer; - BindingPointer texture2D; - BindingPointer textureCubeMap; GLuint readFramebuffer; GLuint drawFramebuffer; BindingPointer renderbuffer; GLuint currentProgram; - AttributeState vertexAttribute[MAX_VERTEX_ATTRIBS]; + VertexAttribute vertexAttribute[MAX_VERTEX_ATTRIBS]; BindingPointer samplerTexture[SAMPLER_TYPE_COUNT][MAX_TEXTURE_IMAGE_UNITS]; GLint unpackAlignment; @@ -264,6 +289,7 @@ class Context void setLineWidth(GLfloat width); void setGenerateMipmapHint(GLenum hint); + void setFragmentShaderDerivativeHint(GLenum hint); void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height); @@ -280,13 +306,13 @@ class Context GLuint getArrayBufferHandle() const; - void setVertexAttribEnabled(unsigned int attribNum, bool enabled); - const AttributeState &getVertexAttribState(unsigned int attribNum); + 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 AttributeState *getVertexAttribBlock(); + const VertexAttributeArray &getVertexAttributes(); void setUnpackAlignment(GLint alignment); GLint getUnpackAlignment() const; @@ -312,6 +338,10 @@ class Context 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); @@ -328,6 +358,7 @@ class Context 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); @@ -351,20 +382,22 @@ class Context bool applyRenderTarget(bool ignoreViewport); void applyState(GLenum drawMode); - GLenum applyVertexBuffer(GLenum mode, GLint first, GLsizei count, bool *useIndexing, TranslatedIndexData *indexInfo); - GLenum applyVertexBuffer(const TranslatedIndexData &indexInfo); + GLenum applyVertexBuffer(GLint first, GLsizei count); GLenum applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); - GLenum applyCountingIndexBuffer(GLenum mode, GLenum count, TranslatedIndexData *indexInfo); void applyShaders(); void applyTextures(); void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels); void clear(GLbitfield mask); void drawArrays(GLenum mode, GLint first, GLsizei count); - void drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices); + void 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(); @@ -374,10 +407,26 @@ class Context GLenum getError(); bool supportsShaderModel3() const; + int getMaximumVaryingVectors() 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; void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, @@ -406,25 +455,24 @@ class Context State mState; - Texture2D *mTexture2DZero; - TextureCubeMap *mTextureCubeMapZero; - - Colorbuffer *mColorbufferZero; - DepthStencilbuffer *mDepthStencilbufferZero; + BindingPointer mTexture2DZero; + BindingPointer mTextureCubeMapZero; typedef std::map FramebufferMap; FramebufferMap mFramebufferMap; + typedef std::map FenceMap; + FenceMap mFenceMap; + void initExtensionString(); std::string mExtensionString; - BufferBackEnd *mBufferBackEnd; VertexDataManager *mVertexDataManager; IndexDataManager *mIndexDataManager; Blit *mBlit; - Texture *mIncompleteTextures[SAMPLER_TYPE_COUNT]; + BindingPointer mIncompleteTextures[SAMPLER_TYPE_COUNT]; // Recorded errors bool mInvalidEnum; @@ -439,11 +487,26 @@ class Context unsigned int mAppliedRenderTargetSerial; unsigned int mAppliedDepthbufferSerial; unsigned int mAppliedStencilbufferSerial; + bool mDepthStencilInitialized; bool mSupportsShaderModel3; + int mMaxRenderbufferDimension; + int mMaxTextureDimension; + int mMaxCubeTextureDimension; + int mMaxTextureLevel; std::map 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; diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Fence.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Fence.cpp new file mode 100644 index 0000000..7fbcb6a --- /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 0000000..17bad78 --- /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 +#include + +#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 index 5c4bc99..5fe01e0 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.cpp +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.cpp @@ -305,13 +305,32 @@ GLenum Framebuffer::completeness() return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - if (IsTextureTarget(mColorbufferType)) + if (mColorbufferType == GL_RENDERBUFFER) + { + if (!gl::IsColorRenderable(colorbuffer->getFormat())) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + else if (IsTextureTarget(mColorbufferType)) { if (IsCompressed(colorbuffer->getFormat())) { return GL_FRAMEBUFFER_UNSUPPORTED; } + + if (colorbuffer->isFloatingPoint() && (!getContext()->supportsFloatRenderableTextures() || + !getContext()->supportsHalfFloatRenderableTextures())) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + if (colorbuffer->getFormat() == GL_LUMINANCE || colorbuffer->getFormat() == GL_LUMINANCE_ALPHA) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } } + else UNREACHABLE(); width = colorbuffer->getWidth(); height = colorbuffer->getHeight(); @@ -327,6 +346,11 @@ GLenum Framebuffer::completeness() if (mDepthbufferType != GL_NONE) { + if (mDepthbufferType != GL_RENDERBUFFER) + { + return GL_FRAMEBUFFER_UNSUPPORTED; // Requires GL_OES_depth_texture + } + depthbuffer = getDepthbuffer(); if (!depthbuffer) @@ -357,18 +381,15 @@ GLenum Framebuffer::completeness() { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; } - - if (IsTextureTarget(mDepthbufferType)) - { - if (IsCompressed(depthbuffer->getFormat())) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - } } if (mStencilbufferType != GL_NONE) { + if (mStencilbufferType != GL_RENDERBUFFER) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + stencilbuffer = getStencilbuffer(); if (!stencilbuffer) @@ -399,14 +420,6 @@ GLenum Framebuffer::completeness() { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; } - - if (IsTextureTarget(mStencilbufferType)) - { - if (IsCompressed(stencilbuffer->getFormat())) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - } } if (mDepthbufferType == GL_RENDERBUFFER && mStencilbufferType == GL_RENDERBUFFER) @@ -425,8 +438,8 @@ GLenum Framebuffer::completeness() DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *color, DepthStencilbuffer *depthStencil) { mColorbufferType = GL_RENDERBUFFER; - mDepthbufferType = GL_RENDERBUFFER; - mStencilbufferType = GL_RENDERBUFFER; + mDepthbufferType = (depthStencil->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE; + mStencilbufferType = (depthStencil->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE; mColorbufferPointer.set(new Renderbuffer(0, color)); @@ -449,6 +462,9 @@ int Framebuffer::getSamples() 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/Program.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Program.cpp index a32bc9f..780c3e3 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/Program.cpp +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Program.cpp @@ -45,7 +45,7 @@ UniformLocation::UniformLocation(const std::string &name, unsigned int element, { } -Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle) +Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle), mSerial(issueSerial()) { mFragmentShader = NULL; mVertexShader = NULL; @@ -63,8 +63,6 @@ Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(man mDeleteStatus = false; mRefCount = 0; - - mSerial = issueSerial(); } Program::~Program() @@ -205,7 +203,7 @@ GLint Program::getSamplerMapping(unsigned int samplerIndex) logicalTextureUnit = mSamplers[samplerIndex].logicalTextureUnit; } - if (logicalTextureUnit < MAX_TEXTURE_IMAGE_UNITS) + if (logicalTextureUnit >= 0 && logicalTextureUnit < MAX_TEXTURE_IMAGE_UNITS) { return logicalTextureUnit; } @@ -243,26 +241,22 @@ void Program::setSamplerDirty(unsigned int samplerIndex, bool dirty) GLint Program::getUniformLocation(const char *name, bool decorated) { - std::string nameStr(name); + std::string _name = decorated ? name : decorate(name); int subscript = 0; - size_t beginB = nameStr.find('['); - size_t endB = nameStr.find(']'); - if (beginB != std::string::npos && endB != std::string::npos) - { - std::string subscrStr = nameStr.substr(beginB + 1, beginB - endB - 1); - nameStr.erase(beginB); - subscript = atoi(subscrStr.c_str()); - } - if (!decorated) + // 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) { - nameStr = decorate(nameStr); + 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 == nameStr && + if (mUniformIndex[location].name == _name && mUniformIndex[location].element == subscript) { return location; @@ -595,7 +589,9 @@ bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v) Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; targetUniform->dirty = true; - if (targetUniform->type == GL_INT) + if (targetUniform->type == GL_INT || + targetUniform->type == GL_SAMPLER_2D || + targetUniform->type == GL_SAMPLER_CUBE) { int arraySize = targetUniform->arraySize; @@ -949,6 +945,8 @@ void Program::applyUniforms() 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; @@ -1001,6 +999,9 @@ ID3DXBuffer *Program::compileToBinary(const char *hlsl, const char *profile, ID3 // 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; @@ -1009,7 +1010,7 @@ int Program::packVaryings(const Varying *packing[][4]) if (m == 2 || m == 3 || m == 4) { - for (int r = 0; r <= MAX_VARYING_VECTORS - n && !success; r++) + for (int r = 0; r <= maxVaryingVectors - n && !success; r++) { bool available = true; @@ -1043,7 +1044,7 @@ int Program::packVaryings(const Varying *packing[][4]) if (!success && m == 2) { - for (int r = MAX_VARYING_VECTORS - n; r >= 0 && !success; r--) + for (int r = maxVaryingVectors - n; r >= 0 && !success; r--) { bool available = true; @@ -1080,7 +1081,7 @@ int Program::packVaryings(const Varying *packing[][4]) { int space[4] = {0}; - for (int y = 0; y < MAX_VARYING_VECTORS; y++) + for (int y = 0; y < maxVaryingVectors; y++) { for (int x = 0; x < 4; x++) { @@ -1100,7 +1101,7 @@ int Program::packVaryings(const Varying *packing[][4]) if (space[column] > n) { - for (int r = 0; r < MAX_VARYING_VECTORS; r++) + for (int r = 0; r < maxVaryingVectors; r++) { if (!packing[r][column]) { @@ -1133,7 +1134,7 @@ int Program::packVaryings(const Varying *packing[][4]) // Return the number of used registers int registers = 0; - for (int r = 0; r < MAX_VARYING_VECTORS; r++) + for (int r = 0; r < maxVaryingVectors; r++) { if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3]) { @@ -1151,7 +1152,7 @@ bool Program::linkVaryings() return false; } - const Varying *packing[MAX_VARYING_VECTORS][4] = {NULL}; + const Varying *packing[MAX_VARYING_VECTORS_SM3][4] = {NULL}; int registers = packVaryings(packing); if (registers < 0) @@ -1159,7 +1160,11 @@ bool Program::linkVaryings() return false; } - if (registers == MAX_VARYING_VECTORS && mFragmentShader->mUsesFragCoord) + 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"); @@ -1197,8 +1202,6 @@ bool Program::linkVaryings() } } - Context *context = getContext(); - bool sm3 = context->supportsShaderModel3(); std::string varyingSemantic = (sm3 ? "COLOR" : "TEXCOORD"); mVertexHLSL += "struct VS_INPUT\n" @@ -1371,6 +1374,9 @@ bool Program::linkVaryings() if (mFragmentShader->mUsesFragCoord) { mPixelHLSL += " float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n"; + if (sm3) { + mPixelHLSL += " float2 dx_VPos : VPOS;\n"; + } } if (mFragmentShader->mUsesPointCoord && sm3) @@ -1395,10 +1401,15 @@ bool Program::linkVaryings() if (mFragmentShader->mUsesFragCoord) { - mPixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n" - " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_Viewport.x + dx_Viewport.z;\n" - " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_Viewport.y + dx_Viewport.w;\n" - " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_Depth.x + dx_Depth.y;\n" + mPixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n"; + if (sm3) { + mPixelHLSL += " gl_FragCoord.x = input.dx_VPos.x;\n" + " gl_FragCoord.y = input.dx_VPos.y;\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"; } @@ -1525,9 +1536,7 @@ void Program::link() // these uniforms are searched as already-decorated because gl_ and dx_ // are reserved prefixes, and do not receive additional decoration - mDepthRangeNearLocation = getUniformLocation("gl_DepthRange.near", true); - mDepthRangeFarLocation = getUniformLocation("gl_DepthRange.far", true); - mDepthRangeDiffLocation = getUniformLocation("gl_DepthRange.diff", true); + mDxDepthRangeLocation = getUniformLocation("dx_DepthRange", true); mDxDepthLocation = getUniformLocation("dx_Depth", true); mDxViewportLocation = getUniformLocation("dx_Viewport", true); mDxHalfPixelSizeLocation = getUniformLocation("dx_HalfPixelSize", true); @@ -1650,32 +1659,38 @@ bool Program::defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT { if (constantDescription.RegisterSet == D3DXRS_SAMPLER) { - unsigned int samplerIndex = constantDescription.RegisterIndex; - - assert(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0])); + for (unsigned int samplerIndex = constantDescription.RegisterIndex; samplerIndex < constantDescription.RegisterIndex + constantDescription.RegisterCount; samplerIndex++) + { + ASSERT(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0])); - mSamplers[samplerIndex].active = true; - mSamplers[samplerIndex].type = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? SAMPLER_CUBE : SAMPLER_2D; - mSamplers[samplerIndex].logicalTextureUnit = 0; - mSamplers[samplerIndex].dirty = true; + mSamplers[samplerIndex].active = true; + mSamplers[samplerIndex].type = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? SAMPLER_CUBE : SAMPLER_2D; + mSamplers[samplerIndex].logicalTextureUnit = 0; + mSamplers[samplerIndex].dirty = true; + } } switch(constantDescription.Class) { case D3DXPC_STRUCT: { - for (unsigned int field = 0; field < constantDescription.StructMembers; field++) + for (unsigned int arrayIndex = 0; arrayIndex < constantDescription.Elements; arrayIndex++) { - D3DXHANDLE fieldHandle = mConstantTablePS->GetConstant(constantHandle, field); + for (unsigned int field = 0; field < constantDescription.StructMembers; field++) + { + D3DXHANDLE fieldHandle = mConstantTablePS->GetConstant(constantHandle, field); - D3DXCONSTANT_DESC fieldDescription; - UINT descriptionCount = 1; + D3DXCONSTANT_DESC fieldDescription; + UINT descriptionCount = 1; - mConstantTablePS->GetConstantDesc(fieldHandle, &fieldDescription, &descriptionCount); + mConstantTablePS->GetConstantDesc(fieldHandle, &fieldDescription, &descriptionCount); - if (!defineUniform(fieldHandle, fieldDescription, name + constantDescription.Name + ".")) - { - return false; + std::string structIndex = (constantDescription.Elements > 1) ? ("[" + str(arrayIndex) + "]") : ""; + + if (!defineUniform(fieldHandle, fieldDescription, name + constantDescription.Name + structIndex + ".")) + { + return false; + } } } @@ -1737,10 +1752,16 @@ Uniform *Program::createUniform(const D3DXCONSTANT_DESC &constantDescription, st 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_INT, name, constantDescription.Elements); + case 1: return new Uniform(GL_SAMPLER_CUBE, name, constantDescription.Elements); default: UNREACHABLE(); } break; @@ -2205,14 +2226,14 @@ bool Program::applyUniform1iv(GLint location, GLsizei count, const GLint *v) { unsigned int firstIndex = mConstantTablePS->GetSamplerIndex(constantPS); - for (unsigned int samplerIndex = firstIndex; samplerIndex < firstIndex + count; samplerIndex++) + for (int i = 0; i < count; i++) { - GLint mappedSampler = v[0]; + unsigned int samplerIndex = firstIndex + i; - if (samplerIndex >= 0 && samplerIndex < MAX_TEXTURE_IMAGE_UNITS) + if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS) { ASSERT(mSamplers[samplerIndex].active); - mSamplers[samplerIndex].logicalTextureUnit = mappedSampler; + mSamplers[samplerIndex].logicalTextureUnit = v[i]; mSamplers[samplerIndex].dirty = true; } } @@ -2371,6 +2392,7 @@ void Program::resetInfoLog() if (mInfoLog) { delete [] mInfoLog; + mInfoLog = NULL; } } @@ -2434,9 +2456,7 @@ void Program::unlink(bool destroy) mUniforms.pop_back(); } - mDepthRangeDiffLocation = -1; - mDepthRangeNearLocation = -1; - mDepthRangeFarLocation = -1; + mDxDepthRangeLocation = -1; mDxDepthLocation = -1; mDxViewportLocation = -1; mDxHalfPixelSizeLocation = -1; @@ -2562,16 +2582,22 @@ void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shade void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) { - unsigned int attribute = 0; - for (unsigned int i = 0; i < index; i++) + // Skip over inactive attributes + unsigned int activeAttribute = 0; + unsigned int attribute; + for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++) { - do + if (mLinkedAttribute[attribute].name.empty()) { - attribute++; + continue; + } - ASSERT(attribute < MAX_VERTEX_ATTRIBS); // index must be smaller than getActiveAttributeCount() + if (activeAttribute == index) + { + break; } - while (mLinkedAttribute[attribute].name.empty()); + + activeAttribute++; } if (bufsize > 0) @@ -2624,18 +2650,26 @@ GLint Program::getActiveAttributeMaxLength() void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) { - unsigned int uniform = 0; - for (unsigned int i = 0; i < index; i++) + // Skip over internal uniforms + unsigned int activeUniform = 0; + unsigned int uniform; + for (uniform = 0; uniform < mUniforms.size(); uniform++) { - do + if (mUniforms[uniform]->name.substr(0, 3) == "dx_") { - uniform++; + continue; + } - ASSERT(uniform < mUniforms.size()); // index must be smaller than getActiveUniformCount() + if (activeUniform == index) + { + break; } - while (mUniforms[uniform]->name.substr(0, 3) == "dx_"); + + activeUniform++; } + ASSERT(uniform < mUniforms.size()); // index must be smaller than getActiveUniformCount() + if (bufsize > 0) { std::string string = undecorate(mUniforms[uniform]->name); @@ -2763,19 +2797,9 @@ void Program::getConstantHandles(Uniform *targetUniform, D3DXHANDLE *constantPS, *constantVS = targetUniform->vsHandle; } -GLint Program::getDepthRangeDiffLocation() const -{ - return mDepthRangeDiffLocation; -} - -GLint Program::getDepthRangeNearLocation() const -{ - return mDepthRangeNearLocation; -} - -GLint Program::getDepthRangeFarLocation() const +GLint Program::getDxDepthRangeLocation() const { - return mDepthRangeFarLocation; + return mDxDepthRangeLocation; } GLint Program::getDxDepthLocation() const diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Program.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Program.h index 3021b7a..e9c149e 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/Program.h +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Program.h @@ -94,9 +94,7 @@ class Program bool getUniformfv(GLint location, GLfloat *params); bool getUniformiv(GLint location, GLint *params); - GLint getDepthRangeDiffLocation() const; - GLint getDepthRangeNearLocation() const; - GLint getDepthRangeFarLocation() const; + GLint getDxDepthRangeLocation() const; GLint getDxDepthLocation() const; GLint getDxViewportLocation() const; GLint getDxHalfPixelSizeLocation() const; @@ -204,9 +202,7 @@ class Program typedef std::vector UniformIndex; UniformIndex mUniformIndex; - GLint mDepthRangeDiffLocation; - GLint mDepthRangeNearLocation; - GLint mDepthRangeFarLocation; + GLint mDxDepthRangeLocation; GLint mDxDepthLocation; GLint mDxViewportLocation; GLint mDxHalfPixelSizeLocation; @@ -220,7 +216,7 @@ class Program unsigned int mRefCount; - unsigned int mSerial; + const unsigned int mSerial; static unsigned int mCurrentSerial; diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/RefCountObject.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/RefCountObject.cpp index e3fd36e..2de1e71 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/RefCountObject.cpp +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/RefCountObject.cpp @@ -22,6 +22,7 @@ RefCountObject::RefCountObject(GLuint id) RefCountObject::~RefCountObject() { + ASSERT(mRefCount == 0); } void RefCountObject::addRef() const diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.cpp index 0eb4637..6e4494b 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.cpp +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.cpp @@ -11,6 +11,7 @@ #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/main.h" +#include "libGLESv2/Texture.h" #include "libGLESv2/utilities.h" namespace gl @@ -86,9 +87,13 @@ void Renderbuffer::setStorage(RenderbufferStorage *newStorage) mStorage = newStorage; } -RenderbufferStorage::RenderbufferStorage() +RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerial()) { - mSerial = issueSerial(); + mWidth = 0; + mHeight = 0; + mFormat = GL_RGBA4; + mD3DFormat = D3DFMT_A8R8G8B8; + mSamples = 0; } RenderbufferStorage::~RenderbufferStorage() @@ -141,6 +146,11 @@ GLenum RenderbufferStorage::getFormat() const return mFormat; } +bool RenderbufferStorage::isFloatingPoint() const +{ + return false; // no floating point renderbuffers +} + D3DFORMAT RenderbufferStorage::getD3DFormat() const { return mD3DFormat; @@ -171,14 +181,17 @@ Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(render renderTarget->GetDesc(&description); setSize(description.Width, description.Height); + mFormat = dx2es::ConvertBackBufferFormat(description.Format); mD3DFormat = description.Format; mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType); } - else - { - mD3DFormat = D3DFMT_UNKNOWN; - mSamples = 0; - } +} + +Colorbuffer::Colorbuffer(const Texture* texture) : mRenderTarget(NULL) +{ + setSize(texture->getWidth(), texture->getHeight()); + mD3DFormat = texture->getD3DFormat(); + mSamples = 0; } Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) @@ -218,13 +231,6 @@ Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) mD3DFormat = requestedFormat; mSamples = supportedSamples; } - else - { - setSize(0, 0); - mFormat = GL_RGBA4; - mD3DFormat = D3DFMT_UNKNOWN; - mSamples = 0; - } } Colorbuffer::~Colorbuffer() @@ -307,15 +313,10 @@ DepthStencilbuffer::DepthStencilbuffer(IDirect3DSurface9 *depthStencil) : mDepth depthStencil->GetDesc(&description); setSize(description.Width, description.Height); - mFormat = (description.Format == D3DFMT_D16 ? GL_DEPTH_COMPONENT16 : GL_DEPTH24_STENCIL8_OES); + mFormat = dx2es::ConvertDepthStencilFormat(description.Format); mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType); mD3DFormat = description.Format; } - else - { - mD3DFormat = D3DFMT_UNKNOWN; - mSamples = 0; - } } DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples) @@ -352,13 +353,6 @@ DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples) mD3DFormat = D3DFMT_D24S8; mSamples = supportedSamples; } - else - { - setSize(0, 0); - mFormat = GL_RGBA4; //default format - mD3DFormat = D3DFMT_UNKNOWN; - mSamples = 0; - } } DepthStencilbuffer::~DepthStencilbuffer() diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.h index cb8c06a..98510c2 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.h +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.h @@ -21,6 +21,7 @@ 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 @@ -42,6 +43,7 @@ class RenderbufferStorage virtual int getWidth() const; virtual int getHeight() const; virtual GLenum getFormat() const; + virtual bool isFloatingPoint() const; D3DFORMAT getD3DFormat() const; GLsizei getSamples() const; unsigned int getSerial() const; @@ -53,7 +55,7 @@ class RenderbufferStorage GLenum mFormat; D3DFORMAT mD3DFormat; GLsizei mSamples; - unsigned int mSerial; + const unsigned int mSerial; private: DISALLOW_COPY_AND_ASSIGN(RenderbufferStorage); @@ -100,6 +102,7 @@ class Colorbuffer : public RenderbufferStorage { public: explicit Colorbuffer(IDirect3DSurface9 *renderTarget); + explicit Colorbuffer(const Texture* texture); Colorbuffer(int width, int height, GLenum format, GLsizei samples); ~Colorbuffer(); diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.cpp index b73ef2a..4c969d6 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.cpp +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.cpp @@ -34,19 +34,22 @@ Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mReso if (result) { - TBuiltInResource resources; - ShInitBuiltInResource(&resources); + ShBuiltInResources resources; + ShInitBuiltInResources(&resources); + Context *context = getContext(); + resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS; resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS; - resources.MaxVaryingVectors = MAX_VARYING_VECTORS; + resources.MaxVaryingVectors = context->getMaximumVaryingVectors(); resources.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS; resources.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS; resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; - resources.MaxFragmentUniformVectors = MAX_FRAGMENT_UNIFORM_VECTORS; + resources.MaxFragmentUniformVectors = context->getMaximumFragmentUniformVectors(); resources.MaxDrawBuffers = MAX_DRAW_BUFFERS; + resources.OES_standard_derivatives = 1; - mFragmentCompiler = ShConstructCompiler(EShLangFragment, EShSpecGLES2, &resources); - mVertexCompiler = ShConstructCompiler(EShLangVertex, EShSpecGLES2, &resources); + mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, &resources); + mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, &resources); } } @@ -240,7 +243,7 @@ void Shader::parseVaryings() char varyingType[256]; char varyingName[256]; - int matches = sscanf(input, "static %s %s", varyingType, varyingName); + int matches = sscanf(input, "static %255s %255s", varyingType, varyingName); if (matches != 2) { @@ -280,21 +283,23 @@ void Shader::compileToHLSL(void *compiler) delete[] mInfoLog; mInfoLog = NULL; - int result = ShCompile(compiler, &mSource, 1, EShOptNone, EDebugOpNone); - const char *obj = ShGetObjectCode(compiler); - const char *info = ShGetInfoLog(compiler); + int result = ShCompile(compiler, &mSource, 1, SH_OBJECT_CODE); if (result) { - mHlsl = new char[strlen(obj) + 1]; - strcpy(mHlsl, obj); + int objCodeLen = 0; + ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen); + mHlsl = new char[objCodeLen]; + ShGetObjectCode(compiler, mHlsl); TRACE("\n%s", mHlsl); } else { - mInfoLog = new char[strlen(info) + 1]; - strcpy(mInfoLog, info); + int infoLogLen = 0; + ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen); + mInfoLog = new char[infoLogLen]; + ShGetInfoLog(compiler, mInfoLog); TRACE("\n%s", mInfoLog); } @@ -468,7 +473,7 @@ void VertexShader::parseAttributes() char attributeType[256]; char attributeName[256]; - int matches = sscanf(input, "static %s _%s", attributeType, attributeName); + int matches = sscanf(input, "static %255s _%255s", attributeType, attributeName); if (matches != 2) { diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp index 2e0b1e3..7c040f8 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp @@ -10,6 +10,8 @@ #include "libGLESv2/Texture.h" +#include + #include #include "common/debug.h" @@ -45,6 +47,7 @@ Texture::Texture(GLuint id) : RefCountObject(id) mDirtyMetaData = true; mDirty = true; mIsRenderable = false; + mType = GL_UNSIGNED_BYTE; mBaseTexture = NULL; } @@ -174,86 +177,171 @@ GLuint Texture::getHeight() const return mHeight; } +bool Texture::isFloatingPoint() const +{ + return (mType == GL_FLOAT || mType == GL_HALF_FLOAT_OES); +} + +bool Texture::isRenderableFormat() const +{ + D3DFORMAT format = getD3DFormat(); + + switch(format) + { + 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; +} + // Selects an internal Direct3D 9 format for storing an Image -D3DFORMAT Texture::selectFormat(GLenum format) +D3DFORMAT Texture::selectFormat(GLenum format, GLenum type) { if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) { return D3DFMT_DXT1; } - else + 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; } -} -int Texture::imagePitch(const Image &img) const -{ - return img.width * 4; + return D3DFMT_A8R8G8B8; } // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input -// into the BGRA8 pixel rectangle at output with outputPitch bytes in between each line. +// 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) const + GLint unpackAlignment, const void *input, size_t outputPitch, void *output, D3DSURFACE_DESC *description) const { GLsizei inputPitch = ComputePitch(width, format, type, unpackAlignment); - switch (format) + switch (type) { - case GL_ALPHA: - loadAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); - break; - - case GL_LUMINANCE: - loadLuminanceImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); - break; - - case GL_LUMINANCE_ALPHA: - loadLuminanceAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); - break; - - case GL_RGB: - switch (type) + case GL_UNSIGNED_BYTE: + switch (format) { - case GL_UNSIGNED_BYTE: + 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_UNSIGNED_SHORT_5_6_5: - loadRGB565ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + case GL_RGBA: + 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_RGBA: - switch (type) + case GL_UNSIGNED_SHORT_5_6_5: + switch (format) { - case GL_UNSIGNED_BYTE: - loadRGBAUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + case GL_RGB: + loadRGB565ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); break; - - case GL_UNSIGNED_SHORT_4_4_4_4: + 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; - - case GL_UNSIGNED_SHORT_5_5_5_1: + 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_BGRA_EXT: - switch (type) + case GL_FLOAT: + switch (format) { - case GL_UNSIGNED_BYTE: - loadBGRAImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output); + // 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; @@ -281,36 +369,174 @@ void Texture::loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GL } } +void Texture::loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + size_t 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(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(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, + size_t 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(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(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, - size_t inputPitch, const void *input, size_t outputPitch, void *output) const + size_t 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(input) + y * inputPitch; - dest = static_cast(output) + (y + yoffset) * outputPitch + xoffset * 4; + dest = static_cast(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, + size_t 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(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(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] = 0xFF; + dest[4 * x + 3] = 1.0f; + } + } +} + +void Texture::loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + size_t inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const unsigned short *source = NULL; + unsigned short *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(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, - size_t inputPitch, const void *input, size_t outputPitch, void *output) const + size_t 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(input) + y * inputPitch; - dest = static_cast(output) + (y + yoffset) * outputPitch + xoffset * 4; + dest = static_cast(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, + size_t 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(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(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, + size_t 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(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + (y + yoffset) * outputPitch + xoffset * 8); for (int x = 0; x < width; x++) { dest[4 * x + 0] = source[2*x+0]; @@ -362,6 +588,46 @@ void Texture::loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, G } } +void Texture::loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + size_t 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(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(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, + size_t 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(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(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::loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, size_t inputPitch, const void *input, size_t outputPitch, void *output) const { @@ -424,6 +690,34 @@ void Texture::loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, } } +void Texture::loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + size_t 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(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + (y + yoffset) * outputPitch + xoffset * 16); + memcpy(dest, source, width * 16); + } +} + +void Texture::loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + size_t inputPitch, const void *input, size_t outputPitch, void *output) const +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = static_cast(output) + (y + yoffset) * outputPitch + xoffset * 8; + memcpy(dest, source, width * 8); + } +} + void Texture::loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, size_t inputPitch, const void *input, size_t outputPitch, void *output) const { @@ -438,7 +732,7 @@ void Texture::loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLs } } -void Texture::createSurface(GLsizei width, GLsizei height, GLenum format, Image *img) +void Texture::createSurface(GLsizei width, GLsizei height, GLenum format, GLenum type, Image *img) { IDirect3DTexture9 *newTexture = NULL; IDirect3DSurface9 *newSurface = NULL; @@ -465,7 +759,7 @@ void Texture::createSurface(GLsizei width, GLsizei height, GLenum format, Image levelToFetch = upsampleCount; } - HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, selectFormat(format), + HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, selectFormat(format, type), D3DPOOL_SYSTEMMEM, &newTexture, NULL); if (FAILED(result)) @@ -488,10 +782,13 @@ void Texture::createSurface(GLsizei width, GLsizei height, GLenum format, Image void Texture::setImage(GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img) { - createSurface(width, height, format, img); + createSurface(width, height, format, type, img); if (pixels != NULL && img->surface != NULL) { + D3DSURFACE_DESC description; + img->surface->GetDesc(&description); + D3DLOCKED_RECT locked; HRESULT result = img->surface->LockRect(&locked, NULL, 0); @@ -499,7 +796,7 @@ void Texture::setImage(GLsizei width, GLsizei height, GLenum format, GLenum type if (SUCCEEDED(result)) { - loadImageData(0, 0, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits); + loadImageData(0, 0, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description); img->surface->UnlockRect(); } @@ -511,7 +808,7 @@ void Texture::setImage(GLsizei width, GLsizei height, GLenum format, GLenum type void Texture::setCompressedImage(GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img) { - createSurface(width, height, format, img); + createSurface(width, height, format, GL_UNSIGNED_BYTE, img); if (pixels != NULL && img->surface != NULL) { @@ -540,18 +837,30 @@ bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig return false; } - D3DLOCKED_RECT locked; - HRESULT result = img->surface->LockRect(&locked, NULL, 0); - - ASSERT(SUCCEEDED(result)); + if (!img->surface) + { + createSurface(img->width, img->height, format, type, img); + } - if (SUCCEEDED(result)) + if (pixels != NULL && img->surface != NULL) { - loadImageData(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits); - img->surface->UnlockRect(); + D3DSURFACE_DESC description; + img->surface->GetDesc(&description); + + D3DLOCKED_RECT locked; + HRESULT result = img->surface->LockRect(&locked, NULL, 0); + + ASSERT(SUCCEEDED(result)); + + if (SUCCEEDED(result)) + { + loadImageData(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description); + img->surface->UnlockRect(); + } + + img->dirty = true; } - img->dirty = true; return true; } @@ -569,32 +878,215 @@ bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GL return false; } - RECT updateRegion; - updateRegion.left = xoffset; - updateRegion.right = xoffset + width; - updateRegion.bottom = yoffset + height; - updateRegion.top = yoffset; + if (!img->surface) + { + createSurface(img->width, img->height, format, GL_UNSIGNED_BYTE, img); + } + + if (pixels != NULL && img->surface != NULL) + { + RECT updateRegion; + updateRegion.left = xoffset; + updateRegion.right = xoffset + width; + updateRegion.bottom = yoffset + height; + updateRegion.top = yoffset; - D3DLOCKED_RECT locked; - HRESULT result = img->surface->LockRect(&locked, &updateRegion, 0); + D3DLOCKED_RECT locked; + HRESULT result = img->surface->LockRect(&locked, &updateRegion, 0); - ASSERT(SUCCEEDED(result)); + ASSERT(SUCCEEDED(result)); - if (SUCCEEDED(result)) - { - GLsizei inputPitch = ComputeCompressedPitch(width, format); - int rows = imageSize / inputPitch; - for (int i = 0; i < rows; ++i) + if (SUCCEEDED(result)) { - memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)pixels + i * inputPitch), inputPitch); + GLsizei inputPitch = ComputeCompressedPitch(width, format); + int rows = imageSize / inputPitch; + for (int i = 0; i < rows; ++i) + { + memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)pixels + i * inputPitch), inputPitch); + } + img->surface->UnlockRect(); } - img->surface->UnlockRect(); + + img->dirty = true; } - img->dirty = true; return true; } +// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats +void Texture::copyNonRenderable(Image *image, GLenum internalFormat, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget) +{ + IDirect3DDevice9 *device = getDevice(); + IDirect3DSurface9 *surface = NULL; + D3DSURFACE_DESC description; + renderTarget->GetDesc(&description); + + HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &surface, NULL); + + if (!SUCCEEDED(result)) + { + ERR("Could not create matching destination surface."); + return error(GL_OUT_OF_MEMORY); + } + + result = device->GetRenderTargetData(renderTarget, surface); + + if (!SUCCEEDED(result)) + { + ERR("GetRenderTargetData unexpectedly failed."); + surface->Release(); + return error(GL_OUT_OF_MEMORY); + } + + D3DLOCKED_RECT sourceLock = {0}; + RECT sourceRect = {x, y, x + width, y + height}; + result = surface->LockRect(&sourceLock, &sourceRect, 0); + + if (FAILED(result)) + { + ERR("Failed to lock the source surface (rectangle might be invalid)."); + surface->UnlockRect(); + surface->Release(); + return error(GL_OUT_OF_MEMORY); + } + + if (!image->surface) + { + createSurface(width, height, internalFormat, mType, image); + } + + if (image->surface == NULL) + { + ERR("Failed to create an image surface."); + surface->UnlockRect(); + surface->Release(); + return error(GL_OUT_OF_MEMORY); + } + + D3DLOCKED_RECT destLock = {0}; + RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height}; + result = image->surface->LockRect(&destLock, &destRect, 0); + + if (FAILED(result)) + { + ERR("Failed to lock the destination surface (rectangle might be invalid)."); + surface->UnlockRect(); + surface->Release(); + return error(GL_OUT_OF_MEMORY); + } + + if (destLock.pBits && sourceLock.pBits) + { + unsigned char *source = (unsigned char*)sourceLock.pBits; + unsigned char *dest = (unsigned char*)destLock.pBits; + + switch (description.Format) + { + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + switch(getD3DFormat()) + { + case D3DFMT_L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + dest[x] = source[x * 4 + 2]; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_A8L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + dest[x * 2 + 0] = source[x * 4 + 2]; + dest[x * 2 + 1] = source[x * 4 + 3]; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + case D3DFMT_R5G6B5: + switch(getD3DFormat()) + { + case D3DFMT_L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned char red = source[x * 2 + 1] & 0xF8; + dest[x] = red | (red >> 5); + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + case D3DFMT_A1R5G5B5: + switch(getD3DFormat()) + { + case D3DFMT_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->dirty = true; + mDirtyMetaData = true; + } + + image->surface->UnlockRect(); + surface->UnlockRect(); + surface->Release(); +} + +D3DFORMAT Texture::getD3DFormat() const +{ + return selectFormat(getFormat(), mType); +} + IDirect3DBaseTexture9 *Texture::getTexture() { if (!isComplete()) @@ -683,15 +1175,19 @@ int Texture::levelCount() const return mBaseTexture ? mBaseTexture->GetLevelCount() : 0; } +bool Texture::isRenderable() const +{ + return mIsRenderable; +} + Texture2D::Texture2D(GLuint id) : Texture(id) { mTexture = NULL; - mColorbufferProxy = NULL; } Texture2D::~Texture2D() { - delete mColorbufferProxy; + mColorbufferProxy.set(NULL); if (mTexture) { @@ -714,9 +1210,9 @@ GLenum Texture2D::getFormat() const // for render-to-texture (such as CopyTexImage). We have no way of keeping individual inconsistent levels. // Call this when a particular level of the texture must be defined with a specific format, width and height. // -// Returns true if the existing texture was unsuitable had to be destroyed. If so, it will also set +// Returns true if the existing texture was unsuitable and had to be destroyed. If so, it will also set // a new height and width for the texture by working backwards from the given width and height. -bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height) +bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type) { bool widthOkay = (mWidth >> level == width); bool heightOkay = (mHeight >> level == height); @@ -725,7 +1221,9 @@ bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei widt || (widthOkay && mHeight >> level == 0 && height == 1) || (heightOkay && mWidth >> level == 0 && width == 1)); - bool textureOkay = (sizeOkay && internalFormat == mImageArray[0].format); + bool typeOkay = (type == mType); + + bool textureOkay = (sizeOkay && typeOkay && internalFormat == mImageArray[0].format); if (!textureOkay) { @@ -735,7 +1233,7 @@ bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei widt // Purge all the levels and the texture. - for (int i = 0; i < MAX_TEXTURE_LEVELS; i++) + for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { if (mImageArray[i].surface != NULL) { @@ -756,6 +1254,7 @@ bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei widt mWidth = width << level; mHeight = height << level; mImageArray[0].format = internalFormat; + mType = type; } return !textureOkay; @@ -763,14 +1262,14 @@ bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei widt void Texture2D::setImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) { - redefineTexture(level, internalFormat, width, height); + redefineTexture(level, internalFormat, width, height, type); Texture::setImage(width, height, format, type, unpackAlignment, pixels, &mImageArray[level]); } void Texture2D::setCompressedImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) { - redefineTexture(level, internalFormat, width, height); + redefineTexture(level, internalFormat, width, height, GL_UNSIGNED_BYTE); Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[level]); } @@ -828,29 +1327,46 @@ void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GL void Texture2D::copyImage(GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source) { - if (redefineTexture(level, internalFormat, width, height)) + IDirect3DSurface9 *renderTarget = source->getRenderTarget(); + + if (!renderTarget) { - convertToRenderTarget(); - pushTexture(mTexture, true); + ERR("Failed to retrieve the render target."); + return error(GL_OUT_OF_MEMORY); } - else + + bool redefined = redefineTexture(level, internalFormat, width, height, mType); + + if (!isRenderableFormat()) { - needRenderTarget(); + copyNonRenderable(&mImageArray[level], internalFormat, 0, 0, x, y, width, height, renderTarget); } - - if (width != 0 && height != 0 && level < levelCount()) + else { - RECT sourceRect; - sourceRect.left = x; - sourceRect.right = x + width; - sourceRect.top = y; - sourceRect.bottom = y + height; + if (redefined) + { + convertToRenderTarget(); + pushTexture(mTexture, true); + } + else + { + needRenderTarget(); + } + + if (width != 0 && height != 0 && level < levelCount()) + { + RECT sourceRect; + sourceRect.left = x; + sourceRect.right = x + width; + sourceRect.top = y; + sourceRect.bottom = y + height; - IDirect3DSurface9 *dest; - HRESULT hr = mTexture->GetSurfaceLevel(level, &dest); + IDirect3DSurface9 *dest; + HRESULT hr = mTexture->GetSurfaceLevel(level, &dest); - getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest); - dest->Release(); + getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest); + dest->Release(); + } } mImageArray[level].width = width; @@ -858,36 +1374,53 @@ void Texture2D::copyImage(GLint level, GLenum internalFormat, GLint x, GLint y, mImageArray[level].format = internalFormat; } -void Texture2D::copySubImage(GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source) +void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source) { if (xoffset + width > mImageArray[level].width || yoffset + height > mImageArray[level].height) { return error(GL_INVALID_VALUE); } - if (redefineTexture(0, mImageArray[0].format, mImageArray[0].width, mImageArray[0].height)) + IDirect3DSurface9 *renderTarget = source->getRenderTarget(); + + if (!renderTarget) { - convertToRenderTarget(); - pushTexture(mTexture, true); + ERR("Failed to retrieve the render target."); + return error(GL_OUT_OF_MEMORY); } - else + + bool redefined = redefineTexture(0, mImageArray[0].format, mImageArray[0].width, mImageArray[0].height, mType); + + if (!isRenderableFormat()) { - needRenderTarget(); + copyNonRenderable(&mImageArray[level], getFormat(), xoffset, yoffset, x, y, width, height, renderTarget); } - - if (level < levelCount()) + else { - RECT sourceRect; - sourceRect.left = x; - sourceRect.right = x + width; - sourceRect.top = y; - sourceRect.bottom = y + height; + if (redefined) + { + convertToRenderTarget(); + pushTexture(mTexture, true); + } + else + { + needRenderTarget(); + } + + if (level < levelCount()) + { + RECT sourceRect; + sourceRect.left = x; + sourceRect.right = x + width; + sourceRect.top = y; + sourceRect.bottom = y + height; - IDirect3DSurface9 *dest; - HRESULT hr = mTexture->GetSurfaceLevel(level, &dest); + IDirect3DSurface9 *dest; + HRESULT hr = mTexture->GetSurfaceLevel(level, &dest); - getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0].format, xoffset, yoffset, dest); - dest->Release(); + getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0].format, xoffset, yoffset, dest); + dest->Release(); + } } } @@ -919,6 +1452,16 @@ bool Texture2D::isComplete() const default: UNREACHABLE(); } + if ((getFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) || + (getFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter())) + { + if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST)) + { + return false; + } + } + + if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width)) || (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height))) { @@ -967,7 +1510,7 @@ IDirect3DBaseTexture9 *Texture2D::createTexture() IDirect3DTexture9 *texture; IDirect3DDevice9 *device = getDevice(); - D3DFORMAT format = selectFormat(mImageArray[0].format); + D3DFORMAT format = selectFormat(mImageArray[0].format, mType); HRESULT result = device->CreateTexture(mWidth, mHeight, creationLevels(mWidth, mHeight, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL); @@ -1018,7 +1561,7 @@ IDirect3DBaseTexture9 *Texture2D::convertToRenderTarget() { egl::Display *display = getDisplay(); IDirect3DDevice9 *device = getDevice(); - D3DFORMAT format = selectFormat(mImageArray[0].format); + D3DFORMAT format = selectFormat(mImageArray[0].format, mType); HRESULT result = device->CreateTexture(mWidth, mHeight, creationLevels(mWidth, mHeight, 0), D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL); @@ -1123,23 +1666,50 @@ void Texture2D::generateMipmaps() mImageArray[i].height = std::max(mImageArray[0].height >> i, 1); } - needRenderTarget(); - - for (unsigned int i = 1; i <= q; i++) + if (isRenderable()) { - IDirect3DSurface9 *upper = NULL; - IDirect3DSurface9 *lower = NULL; + if (mTexture == NULL) + { + ERR(" failed because mTexture was null."); + return; + } - mTexture->GetSurfaceLevel(i-1, &upper); - mTexture->GetSurfaceLevel(i, &lower); + 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 && lower != NULL) + if (upper != NULL) upper->Release(); + if (lower != NULL) lower->Release(); + } + } + else + { + for (unsigned int i = 1; i <= q; i++) { - getBlitter()->boxFilter(upper, lower); + createSurface(mImageArray[i].width, mImageArray[i].height, mImageArray[i].format, mType, &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; } - if (upper != NULL) upper->Release(); - if (lower != NULL) lower->Release(); + mDirtyMetaData = true; } } @@ -1150,13 +1720,12 @@ Renderbuffer *Texture2D::getColorbuffer(GLenum target) return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL); } - if (mColorbufferProxy == NULL) + if (mColorbufferProxy.get() == NULL) { - mColorbufferProxy = new Renderbuffer(id(), new TextureColorbufferProxy(this, target)); - mColorbufferProxy->addRef(); + mColorbufferProxy.set(new Renderbuffer(id(), new TextureColorbufferProxy(this, target))); } - return mColorbufferProxy; + return mColorbufferProxy.get(); } IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target) @@ -1165,6 +1734,11 @@ IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target) needRenderTarget(); + if (mTexture == NULL) + { + return NULL; + } + IDirect3DSurface9 *renderTarget = NULL; mTexture->GetSurfaceLevel(0, &renderTarget); @@ -1174,18 +1748,13 @@ IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target) TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id) { mTexture = NULL; - - for (int i = 0; i < 6; i++) - { - mFaceProxies[i] = NULL; - } } TextureCubeMap::~TextureCubeMap() { for (int i = 0; i < 6; i++) { - delete mFaceProxies[i]; + mFaceProxies[i].set(NULL); } if (mTexture) @@ -1277,19 +1846,19 @@ void TextureCubeMap::commitRect(GLenum faceTarget, GLint level, GLint xoffset, G } } -void TextureCubeMap::subImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +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(face)][level])) + if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(target)][level])) { - commitRect(face, level, xoffset, yoffset, width, height); + commitRect(target, level, xoffset, yoffset, width, height); } } -void TextureCubeMap::subImageCompressed(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) +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(face)][level])) + if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(target)][level])) { - commitRect(face, level, xoffset, yoffset, width, height); + commitRect(target, level, xoffset, yoffset, width, height); } } @@ -1328,6 +1897,15 @@ bool TextureCubeMap::isComplete() const } } + if ((getFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) || + (getFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter())) + { + if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST)) + { + return false; + } + } + if (mipmapping) { if (!isPow2(size) && (getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE)) @@ -1368,7 +1946,7 @@ bool TextureCubeMap::isCompressed() const IDirect3DBaseTexture9 *TextureCubeMap::createTexture() { IDirect3DDevice9 *device = getDevice(); - D3DFORMAT format = selectFormat(mImageArray[0][0].format); + D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType); IDirect3DCubeTexture9 *texture; @@ -1424,7 +2002,7 @@ IDirect3DBaseTexture9 *TextureCubeMap::convertToRenderTarget() { egl::Display *display = getDisplay(); IDirect3DDevice9 *device = getDevice(); - D3DFORMAT format = selectFormat(mImageArray[0][0].format); + D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType); HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL); @@ -1546,7 +2124,7 @@ bool TextureCubeMap::redefineTexture(GLint level, GLenum internalFormat, GLsizei internalFormat, width); // Purge all the levels and the texture. - for (int i = 0; i < MAX_TEXTURE_LEVELS; i++) + for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { for (int f = 0; f < 6; f++) { @@ -1578,34 +2156,50 @@ bool TextureCubeMap::redefineTexture(GLint level, GLenum internalFormat, GLsizei return !textureOkay; } -void TextureCubeMap::copyImage(GLenum face, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source) +void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source) { - unsigned int faceindex = faceIndex(face); + IDirect3DSurface9 *renderTarget = source->getRenderTarget(); - if (redefineTexture(level, internalFormat, width)) + if (!renderTarget) { - convertToRenderTarget(); - pushTexture(mTexture, true); + ERR("Failed to retrieve the render target."); + return error(GL_OUT_OF_MEMORY); } - else + + unsigned int faceindex = faceIndex(target); + bool redefined = redefineTexture(level, internalFormat, width); + + if (!isRenderableFormat()) { - needRenderTarget(); + copyNonRenderable(&mImageArray[faceindex][level], internalFormat, 0, 0, x, y, width, height, renderTarget); } + else + { + if (redefined) + { + convertToRenderTarget(); + pushTexture(mTexture, true); + } + else + { + needRenderTarget(); + } - ASSERT(width == height); + ASSERT(width == height); - if (width > 0 && level < levelCount()) - { - RECT sourceRect; - sourceRect.left = x; - sourceRect.right = x + width; - sourceRect.top = y; - sourceRect.bottom = y + height; + if (width > 0 && level < levelCount()) + { + RECT sourceRect; + sourceRect.left = x; + sourceRect.right = x + width; + sourceRect.top = y; + sourceRect.bottom = y + height; - IDirect3DSurface9 *dest = getCubeMapSurface(face, level); + IDirect3DSurface9 *dest = getCubeMapSurface(target, level); - getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest); - dest->Release(); + getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest); + dest->Release(); + } } mImageArray[faceindex][level].width = width; @@ -1644,37 +2238,55 @@ IDirect3DSurface9 *TextureCubeMap::getCubeMapSurface(unsigned int faceIdentifier return (SUCCEEDED(hr)) ? surface : NULL; } -void TextureCubeMap::copySubImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source) +void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source) { - GLsizei size = mImageArray[faceIndex(face)][level].width; + GLsizei size = mImageArray[faceIndex(target)][level].width; if (xoffset + width > size || yoffset + height > size) { return error(GL_INVALID_VALUE); } - if (redefineTexture(0, mImageArray[0][0].format, mImageArray[0][0].width)) + IDirect3DSurface9 *renderTarget = source->getRenderTarget(); + + if (!renderTarget) { - convertToRenderTarget(); - pushTexture(mTexture, true); + ERR("Failed to retrieve the render target."); + return error(GL_OUT_OF_MEMORY); } - else + + unsigned int faceindex = faceIndex(target); + bool redefined = redefineTexture(0, mImageArray[0][0].format, mImageArray[0][0].width); + + if (!isRenderableFormat()) { - needRenderTarget(); + copyNonRenderable(&mImageArray[faceindex][level], getFormat(), 0, 0, x, y, width, height, renderTarget); } - - if (level < levelCount()) + else { - RECT sourceRect; - sourceRect.left = x; - sourceRect.right = x + width; - sourceRect.top = y; - sourceRect.bottom = y + height; + if (redefined) + { + convertToRenderTarget(); + pushTexture(mTexture, true); + } + else + { + needRenderTarget(); + } + + if (level < levelCount()) + { + RECT sourceRect; + sourceRect.left = x; + sourceRect.right = x + width; + sourceRect.top = y; + sourceRect.bottom = y + height; - IDirect3DSurface9 *dest = getCubeMapSurface(face, level); + IDirect3DSurface9 *dest = getCubeMapSurface(target, level); - getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0][0].format, xoffset, yoffset, dest); - dest->Release(); + getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0][0].format, xoffset, yoffset, dest); + dest->Release(); + } } } @@ -1724,23 +2336,52 @@ void TextureCubeMap::generateMipmaps() } } - needRenderTarget(); - - for (unsigned int f = 0; f < 6; f++) + if (isRenderable()) { - for (unsigned int i = 1; i <= q; i++) + if (mTexture == NULL) { - IDirect3DSurface9 *upper = getCubeMapSurface(f, i-1); - IDirect3DSurface9 *lower = getCubeMapSurface(f, i); + return; + } - if (upper != NULL && lower != NULL) + for (unsigned int f = 0; f < 6; f++) + { + for (unsigned int i = 1; i <= q; i++) { - getBlitter()->boxFilter(upper, lower); + IDirect3DSurface9 *upper = getCubeMapSurface(f, i-1); + IDirect3DSurface9 *lower = getCubeMapSurface(f, i); + + if (upper != NULL && lower != NULL) + { + getBlitter()->boxFilter(upper, lower); + } + + if (upper != NULL) upper->Release(); + if (lower != NULL) lower->Release(); } + } + } + else + { + for (unsigned int f = 0; f < 6; f++) + { + for (unsigned int i = 1; i <= q; i++) + { + createSurface(mImageArray[f][i].width, mImageArray[f][i].height, mImageArray[f][i].format, mType, &mImageArray[f][i]); + if (mImageArray[f][i].surface == NULL) + { + return error(GL_OUT_OF_MEMORY); + } - if (upper != NULL) upper->Release(); - if (lower != NULL) lower->Release(); + 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; + } } + + mDirtyMetaData = true; } } @@ -1753,13 +2394,12 @@ Renderbuffer *TextureCubeMap::getColorbuffer(GLenum target) unsigned int face = faceIndex(target); - if (mFaceProxies[face] == NULL) + if (mFaceProxies[face].get() == NULL) { - mFaceProxies[face] = new Renderbuffer(id(), new TextureColorbufferProxy(this, target)); - mFaceProxies[face]->addRef(); + mFaceProxies[face].set(new Renderbuffer(id(), new TextureColorbufferProxy(this, target))); } - return mFaceProxies[face]; + return mFaceProxies[face].get(); } IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target) @@ -1767,7 +2407,12 @@ IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target) ASSERT(IsCubemapTextureTarget(target)); needRenderTarget(); - + + if (mTexture == NULL) + { + return NULL; + } + IDirect3DSurface9 *renderTarget = NULL; mTexture->GetCubeMapSurface(static_cast(faceIndex(target)), 0, &renderTarget); @@ -1775,9 +2420,9 @@ IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target) } Texture::TextureColorbufferProxy::TextureColorbufferProxy(Texture *texture, GLenum target) - : Colorbuffer(NULL), mTexture(texture), mTarget(target) + : Colorbuffer(texture), mTexture(texture), mTarget(target) { - ASSERT(target == GL_TEXTURE_2D || IsCubemapTextureTarget(target)); + ASSERT(IsTextureTarget(target)); } void Texture::TextureColorbufferProxy::addRef() const @@ -1814,4 +2459,9 @@ GLenum Texture::TextureColorbufferProxy::getFormat() const return mTexture->getFormat(); } +bool Texture::TextureColorbufferProxy::isFloatingPoint() const +{ + return mTexture->isFloatingPoint(); +} + } diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.h index efa882c..ca7aec7 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.h +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.h @@ -18,6 +18,7 @@ #include #include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/RefCountObject.h" #include "libGLESv2/utilities.h" #include "common/debug.h" @@ -27,10 +28,13 @@ class Blit; enum { - MAX_TEXTURE_SIZE = 2048, - MAX_CUBE_MAP_TEXTURE_SIZE = 2048, + // 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, - MAX_TEXTURE_LEVELS = 12 // 1+log2 of MAX_TEXTURE_SIZE + IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE }; class Texture : public RefCountObject @@ -58,11 +62,15 @@ class Texture : public RefCountObject virtual GLenum getFormat() const = 0; virtual bool isComplete() const = 0; virtual bool isCompressed() const = 0; + bool isFloatingPoint() const; + bool isRenderableFormat() const; + D3DFORMAT getD3DFormat() const; IDirect3DBaseTexture9 *getTexture(); virtual Renderbuffer *getColorbuffer(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, RenderbufferStorage *source) = 0; bool isDirty() const; @@ -85,6 +93,7 @@ class Texture : public RefCountObject virtual int getWidth() const; virtual int getHeight() const; virtual GLenum getFormat() const; + virtual bool isFloatingPoint() const; private: Texture *mTexture; @@ -106,13 +115,13 @@ class Texture : public RefCountObject IDirect3DSurface9 *surface; }; - static D3DFORMAT selectFormat(GLenum format); - int imagePitch(const Image& img) const; + static D3DFORMAT selectFormat(GLenum format, GLenum type); void setImage(GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img); bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img); void setCompressedImage(GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img); bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img); + void copyNonRenderable(Image *image, GLenum internalFormat, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget); void needRenderTarget(); @@ -129,50 +138,73 @@ class Texture : public RefCountObject void dropTexture(); void pushTexture(IDirect3DBaseTexture9 *newTexture, bool renderable); + void createSurface(GLsizei width, GLsizei height, GLenum format, GLenum type, Image *img); Blit *getBlitter(); int levelCount() const; + bool isRenderable() const; + unsigned int mWidth; unsigned int mHeight; GLenum mMinFilter; GLenum mMagFilter; GLenum mWrapS; GLenum mWrapT; + GLenum mType; + + bool mDirtyMetaData; private: DISALLOW_COPY_AND_ASSIGN(Texture); void loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, - GLint unpackAlignment, const void *input, std::size_t outputPitch, void *output) const; + 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, size_t inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + size_t inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + size_t inputPitch, const void *input, size_t outputPitch, void *output) const; void loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - size_t inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + size_t inputPitch, const void *input, size_t outputPitch, void *output, bool native) const; + void loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, size_t inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + size_t inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + size_t inputPitch, const void *input, size_t outputPitch, void *output, bool native) const; + void loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + size_t inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + size_t inputPitch, const void *input, size_t outputPitch, void *output) const; void loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, size_t inputPitch, const void *input, size_t outputPitch, void *output) const; void loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, size_t inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + size_t inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + size_t inputPitch, const void *input, size_t outputPitch, void *output) const; void loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, size_t inputPitch, const void *input, size_t outputPitch, void *output) const; void loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, size_t inputPitch, const void *input, size_t outputPitch, void *output) const; void loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, size_t inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + size_t inputPitch, const void *input, size_t outputPitch, void *output) const; + void loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + size_t inputPitch, const void *input, size_t outputPitch, void *output) const; void loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, size_t inputPitch, const void *input, size_t outputPitch, void *output) const; IDirect3DBaseTexture9 *mBaseTexture; // This is a weak pointer. The derived class is assumed to own a strong pointer. bool mDirty; - bool mDirtyMetaData; bool mIsRenderable; - - void createSurface(GLsizei width, GLsizei height, GLenum format, Image *img); }; class Texture2D : public Texture @@ -190,7 +222,7 @@ class Texture2D : public Texture void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); void copyImage(GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source); - void copySubImage(GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source); + void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source); bool isComplete() const; bool isCompressed() const; @@ -209,14 +241,14 @@ class Texture2D : public Texture virtual bool dirtyImageData() const; - bool redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height); + bool redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type); void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - Image mImageArray[MAX_TEXTURE_LEVELS]; + Image mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS]; IDirect3DTexture9 *mTexture; - Renderbuffer *mColorbufferProxy; + BindingPointer mColorbufferProxy; }; class TextureCubeMap : public Texture @@ -238,10 +270,10 @@ class TextureCubeMap : public Texture void setCompressedImage(GLenum face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); - void subImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); - void subImageCompressed(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); - void copyImage(GLenum face, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source); - void copySubImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source); + 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 internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source); + void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source); bool isComplete() const; bool isCompressed() const; @@ -272,11 +304,11 @@ class TextureCubeMap : public Texture void commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); bool redefineTexture(GLint level, GLenum internalFormat, GLsizei width); - Image mImageArray[6][MAX_TEXTURE_LEVELS]; + Image mImageArray[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS]; IDirect3DCubeTexture9 *mTexture; - Renderbuffer *mFaceProxies[6]; + BindingPointer mFaceProxies[6]; }; } diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp index d573579..f79d606 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp @@ -13,7 +13,7 @@ #include "libGLESv2/Buffer.h" #include "libGLESv2/mathutil.h" -#include "libGLESv2/geometry/backend.h" +#include "libGLESv2/main.h" namespace { @@ -23,239 +23,360 @@ namespace namespace gl { -IndexDataManager::IndexDataManager(Context *context, BufferBackEnd *backend) - : mContext(context), mBackend(backend), mIntIndicesSupported(backend->supportIntIndices()) +IndexDataManager::IndexDataManager(Context *context, IDirect3DDevice9 *device) : mDevice(device) { - mCountingBuffer = NULL; - mCountingBufferSize = 0; + mStreamingBufferShort = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16); - mLineLoopBuffer = NULL; - - mStreamBufferShort = mBackend->createIndexBuffer(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT); - - if (mIntIndicesSupported) + if (context->supports32bitIndices()) { - mStreamBufferInt = mBackend->createIndexBuffer(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); + mStreamingBufferInt = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32); } else { - mStreamBufferInt = NULL; + mStreamingBufferInt = NULL; } } IndexDataManager::~IndexDataManager() { - delete mStreamBufferShort; - delete mStreamBufferInt; - delete mCountingBuffer; - delete mLineLoopBuffer; + delete mStreamingBufferShort; + delete mStreamingBufferInt; } -namespace +void convertIndices(GLenum type, const void *input, GLsizei count, void *output) { + if (type == GL_UNSIGNED_BYTE) + { + const GLubyte *in = static_cast(input); + GLushort *out = static_cast(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 -void copyIndices(const InputIndexType *in, GLsizei count, OutputIndexType *out, GLuint *minIndex, GLuint *maxIndex) +template +void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) { - InputIndexType first = *in; - GLuint minIndexSoFar = first; - GLuint maxIndexSoFar = first; + *minIndex = indices[0]; + *maxIndex = indices[0]; for (GLsizei i = 0; i < count; i++) { - if (minIndexSoFar > *in) minIndexSoFar = *in; - if (maxIndexSoFar < *in) maxIndexSoFar = *in; - - *out++ = *in++; + if (*minIndex > indices[i]) *minIndex = indices[i]; + if (*maxIndex < indices[i]) *maxIndex = indices[i]; } - - // It might be a line loop, so copy the loop index. - *out = first; - - *minIndex = minIndexSoFar; - *maxIndex = maxIndexSoFar; } +void computeRange(GLenum type, const void *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +{ + if (type == GL_UNSIGNED_BYTE) + { + computeRange(static_cast(indices), count, minIndex, maxIndex); + } + else if (type == GL_UNSIGNED_INT) + { + computeRange(static_cast(indices), count, minIndex, maxIndex); + } + else if (type == GL_UNSIGNED_SHORT) + { + computeRange(static_cast(indices), count, minIndex, maxIndex); + } + else UNREACHABLE(); } -GLenum IndexDataManager::preRenderValidate(GLenum mode, GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices, TranslatedIndexData *translated) +GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const void *indices, TranslatedIndexData *translated) { - ASSERT(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT); - ASSERT(count > 0); + D3DFORMAT format = (type == GL_UNSIGNED_INT) ? D3DFMT_INDEX32 : D3DFMT_INDEX16; + intptr_t offset = reinterpret_cast(indices); + bool alignedOffset = false; - if (arrayElementBuffer != NULL) + if (buffer != NULL) { - GLsizei offset = reinterpret_cast(indices); + 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(arrayElementBuffer->size())) + if (typeSize(type) * count + offset > static_cast(buffer->size())) { return GL_INVALID_OPERATION; } - indices = static_cast(arrayElementBuffer->data()) + offset; + indices = static_cast(buffer->data()) + offset; } - translated->count = count; - - std::size_t requiredSpace = spaceRequired(type, count); - - TranslatedIndexBuffer *streamIb = prepareIndexBuffer(type, requiredSpace); + StreamingIndexBuffer *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort; - size_t offset; - void *output = streamIb->map(requiredSpace, &offset); + StaticIndexBuffer *staticBuffer = buffer ? buffer->getIndexBuffer() : NULL; + IndexBuffer *indexBuffer = streamingBuffer; + UINT streamOffset = 0; - translated->buffer = streamIb; - translated->offset = offset; - translated->indexSize = indexSize(type); - - if (type == GL_UNSIGNED_BYTE) + if (staticBuffer && staticBuffer->lookupType(type) && alignedOffset) { - const GLubyte *in = static_cast(indices); - GLushort *out = static_cast(output); + indexBuffer = staticBuffer; + streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex); - copyIndices(in, count, out, &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 if (type == GL_UNSIGNED_INT) + else { - const GLuint *in = static_cast(indices); + int convertCount = count; - if (mIntIndicesSupported) + if (staticBuffer) { - GLuint *out = static_cast(output); + if (staticBuffer->size() == 0 && alignedOffset) + { + indexBuffer = staticBuffer; + convertCount = buffer->size() / typeSize(type); + } + else + { + buffer->invalidateStaticData(); + staticBuffer = NULL; + } + } - copyIndices(in, count, out, &translated->minIndex, &translated->maxIndex); + void *output = NULL; + + if (indexBuffer) + { + indexBuffer->reserveSpace(convertCount * indexSize(format), type); + output = indexBuffer->map(indexSize(format) * convertCount, &streamOffset); } - else + + if (output == NULL) { - // When 32-bit indices are unsupported, fake them by truncating to 16-bit. + ERR("Failed to map index buffer."); + return GL_OUT_OF_MEMORY; + } - GLushort *out = static_cast(output); + convertIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output); + indexBuffer->unmap(); - copyIndices(in, count, out, &translated->minIndex, &translated->maxIndex); - } - } - else - { - const GLushort *in = static_cast(indices); - GLushort *out = static_cast(output); + computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - copyIndices(in, count, out, &translated->minIndex, &translated->maxIndex); + if (staticBuffer) + { + streamOffset = (offset / typeSize(type)) * indexSize(format); + staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset); + } } - streamIb->unmap(); + translated->indexBuffer = indexBuffer->getBuffer(); + translated->startIndex = streamOffset / indexSize(format); return GL_NO_ERROR; } -std::size_t IndexDataManager::indexSize(GLenum type) const +std::size_t IndexDataManager::indexSize(D3DFORMAT format) const { - return (type == GL_UNSIGNED_INT && mIntIndicesSupported) ? sizeof(GLuint) : sizeof(GLushort); + 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_INT: return sizeof(GLuint); case GL_UNSIGNED_SHORT: return sizeof(GLushort); - default: UNREACHABLE(); - case GL_UNSIGNED_BYTE: return sizeof(GLubyte); + case GL_UNSIGNED_BYTE: return sizeof(GLubyte); + default: UNREACHABLE(); return sizeof(GLushort); } } -std::size_t IndexDataManager::spaceRequired(GLenum type, GLsizei count) const +IndexBuffer::IndexBuffer(IDirect3DDevice9 *device, UINT size, D3DFORMAT format) : mDevice(device), mBufferSize(size), mIndexBuffer(NULL) { - return (count + 1) * indexSize(type); // +1 because we always leave an extra for line loops + 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); + } + } } -TranslatedIndexBuffer *IndexDataManager::prepareIndexBuffer(GLenum type, std::size_t requiredSpace) +IndexBuffer::~IndexBuffer() { - bool use32 = (type == GL_UNSIGNED_INT && mIntIndicesSupported); + if (mIndexBuffer) + { + mIndexBuffer->Release(); + } +} - TranslatedIndexBuffer *streamIb = use32 ? mStreamBufferInt : mStreamBufferShort; +IDirect3DIndexBuffer9 *IndexBuffer::getBuffer() const +{ + return mIndexBuffer; +} - if (requiredSpace > streamIb->size()) +void IndexBuffer::unmap() +{ + if (mIndexBuffer) { - std::size_t newSize = std::max(requiredSpace, 2 * streamIb->size()); + mIndexBuffer->Unlock(); + } +} - TranslatedIndexBuffer *newStreamBuffer = mBackend->createIndexBuffer(newSize, use32 ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT); +StreamingIndexBuffer::StreamingIndexBuffer(IDirect3DDevice9 *device, UINT initialSize, D3DFORMAT format) : IndexBuffer(device, initialSize, format) +{ + mWritePosition = 0; +} - delete streamIb; +StreamingIndexBuffer::~StreamingIndexBuffer() +{ +} - streamIb = newStreamBuffer; +void *StreamingIndexBuffer::map(UINT requiredSpace, UINT *offset) +{ + void *mapPtr = NULL; - if (use32) - { - mStreamBufferInt = streamIb; - } - else + if (mIndexBuffer) + { + HRESULT result = mIndexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE); + + if (FAILED(result)) { - mStreamBufferShort = streamIb; + ERR(" Lock failed with error 0x%08x", result); + return NULL; } - } - streamIb->reserveSpace(requiredSpace); + *offset = mWritePosition; + mWritePosition += requiredSpace; + } - return streamIb; + return mapPtr; } -GLenum IndexDataManager::preRenderValidateUnindexed(GLenum mode, GLsizei count, TranslatedIndexData *indexInfo) +void StreamingIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type) { - if (count >= 65535) return GL_OUT_OF_MEMORY; - - if (mode == GL_LINE_LOOP) + if (requiredSpace > mBufferSize) { - // For line loops, create a single-use buffer that runs 0 - count-1, 0. - delete mLineLoopBuffer; - mLineLoopBuffer = mBackend->createIndexBuffer((count+1) * sizeof(unsigned short), GL_UNSIGNED_SHORT); - - unsigned short *indices = static_cast(mLineLoopBuffer->map()); - - for (int i = 0; i < count; i++) + if (mIndexBuffer) { - indices[i] = i; + mIndexBuffer->Release(); + mIndexBuffer = NULL; } - indices[count] = 0; + mBufferSize = std::max(requiredSpace, 2 * mBufferSize); - mLineLoopBuffer->unmap(); + 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); + } - indexInfo->buffer = mLineLoopBuffer; - indexInfo->count = count + 1; - indexInfo->maxIndex = count - 1; + mWritePosition = 0; } - else if (mCountingBufferSize < count) + else if (mWritePosition + requiredSpace > mBufferSize) // Recycle { - mCountingBufferSize = std::max(static_cast(ceilPow2(count)), mCountingBufferSize*2); + void *dummy; + mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); + mIndexBuffer->Unlock(); - delete mCountingBuffer; - mCountingBuffer = mBackend->createIndexBuffer(count * sizeof(unsigned short), GL_UNSIGNED_SHORT); + mWritePosition = 0; + } +} - unsigned short *indices = static_cast(mCountingBuffer->map()); +StaticIndexBuffer::StaticIndexBuffer(IDirect3DDevice9 *device) : IndexBuffer(device, 0, D3DFMT_UNKNOWN) +{ + mCacheType = GL_NONE; +} - for (int i = 0; i < count; i++) +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)) { - indices[i] = i; + ERR(" Lock failed with error 0x%08x", result); + return NULL; } - mCountingBuffer->unmap(); + *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); + } - indexInfo->buffer = mCountingBuffer; - indexInfo->count = count; - indexInfo->maxIndex = count - 1; + mBufferSize = requiredSpace; + mCacheType = type; } - else + else if (mIndexBuffer && mBufferSize >= requiredSpace && mCacheType == type) { - indexInfo->buffer = mCountingBuffer; - indexInfo->count = count; - indexInfo->maxIndex = count - 1; + // Already allocated } + else UNREACHABLE(); // Static index buffers can't be resized +} - indexInfo->indexSize = sizeof(unsigned short); - indexInfo->minIndex = 0; - indexInfo->offset = 0; +bool StaticIndexBuffer::lookupType(GLenum type) +{ + return mCacheType == type; +} - return GL_NO_ERROR; +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 index 00ebed2..d48249c 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.h +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.h @@ -10,7 +10,7 @@ #ifndef LIBGLESV2_GEOMETRY_INDEXDATAMANAGER_H_ #define LIBGLESV2_GEOMETRY_INDEXDATAMANAGER_H_ -#include +#include #include #define GL_APICALL @@ -21,49 +21,98 @@ namespace gl { -class Buffer; -class BufferBackEnd; -class TranslatedIndexBuffer; -struct FormatConverter; - struct TranslatedIndexData { - GLuint minIndex; - GLuint maxIndex; - GLuint count; - GLuint indexSize; + UINT minIndex; + UINT maxIndex; + UINT startIndex; - TranslatedIndexBuffer *buffer; - GLsizei offset; + IDirect3DIndexBuffer9 *indexBuffer; }; -class IndexDataManager +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: - IndexDataManager(Context *context, BufferBackEnd *backend); - ~IndexDataManager(); + explicit StaticIndexBuffer(IDirect3DDevice9 *device); + ~StaticIndexBuffer(); + + void *map(UINT requiredSpace, UINT *offset); + void reserveSpace(UINT requiredSpace, GLenum type); - GLenum preRenderValidate(GLenum mode, GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices, TranslatedIndexData *translated); - GLenum preRenderValidateUnindexed(GLenum mode, GLsizei count, TranslatedIndexData *indexInfo); + 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: - std::size_t IndexDataManager::typeSize(GLenum type) const; - std::size_t IndexDataManager::indexSize(GLenum type) const; - std::size_t spaceRequired(GLenum type, GLsizei count) const; - TranslatedIndexBuffer *prepareIndexBuffer(GLenum type, std::size_t requiredSpace); + GLenum mCacheType; + + struct IndexRange + { + intptr_t offset; + GLsizei count; + + UINT minIndex; + UINT maxIndex; + UINT streamOffset; + }; + + std::vector mCache; +}; + +class IndexDataManager +{ + public: + IndexDataManager(Context *context, IDirect3DDevice9 *evice); + virtual ~IndexDataManager(); - Context *mContext; - BufferBackEnd *mBackend; + GLenum prepareIndexData(GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices, TranslatedIndexData *translated); - bool mIntIndicesSupported; + private: + DISALLOW_COPY_AND_ASSIGN(IndexDataManager); - TranslatedIndexBuffer *mStreamBufferShort; - TranslatedIndexBuffer *mStreamBufferInt; + std::size_t typeSize(GLenum type) const; + std::size_t indexSize(D3DFORMAT format) const; - TranslatedIndexBuffer *mCountingBuffer; - GLsizei mCountingBufferSize; + IDirect3DDevice9 *const mDevice; - TranslatedIndexBuffer *mLineLoopBuffer; + StreamingIndexBuffer *mStreamingBufferShort; + StreamingIndexBuffer *mStreamingBufferInt; }; } diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.cpp index 7762e07..99ece17 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.cpp +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.cpp @@ -9,14 +9,13 @@ #include "libGLESv2/geometry/VertexDataManager.h" -#include - #include "common/debug.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/Program.h" +#include "libGLESv2/main.h" -#include "libGLESv2/geometry/backend.h" +#include "libGLESv2/geometry/vertexconversion.h" #include "libGLESv2/geometry/IndexDataManager.h" namespace @@ -27,245 +26,744 @@ namespace namespace gl { -VertexDataManager::VertexDataManager(Context *context, BufferBackEnd *backend) - : mContext(context), mBackend(backend), mDirtyCurrentValues(true), mCurrentValueOffset(0) +VertexDataManager::VertexDataManager(Context *context, IDirect3DDevice9 *device) : mContext(context), mDevice(device) { - mStreamBuffer = mBackend->createVertexBuffer(INITIAL_STREAM_BUFFER_SIZE); - try - { - mCurrentValueBuffer = mBackend->createVertexBufferForStrideZero(4 * sizeof(float) * MAX_VERTEX_ATTRIBS); - } - catch (...) + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) { - delete mStreamBuffer; - throw; + 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 mStreamBuffer; - delete mCurrentValueBuffer; + delete mStreamingBuffer; + + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + delete mCurrentValueBuffer[i]; + } } -std::bitset VertexDataManager::getActiveAttribs() const +UINT VertexDataManager::writeAttributeData(ArrayVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute) { - std::bitset active; + Buffer *buffer = attribute.mBoundBuffer.get(); - Program *program = mContext->getCurrentProgram(); + int inputStride = attribute.stride(); + int elementSize = attribute.typeSize(); + const FormatConverter &converter = formatConverter(attribute); + UINT streamOffset = 0; - for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + void *output = NULL; + + if (vertexBuffer) { - active[attributeIndex] = (program->getSemanticIndex(attributeIndex) != -1); + output = vertexBuffer->map(attribute, spaceRequired(attribute, count), &streamOffset); } - return active; -} + if (output == NULL) + { + ERR("Failed to map vertex buffer."); + return -1; + } -GLenum VertexDataManager::preRenderValidate(GLint start, GLsizei count, - TranslatedAttribute *translated) -{ - const AttributeState *attribs = mContext->getVertexAttribBlock(); - const std::bitset activeAttribs = getActiveAttribs(); + const char *input = NULL; - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + if (buffer) + { + int offset = attribute.mOffset; + + input = static_cast(buffer->data()) + offset; + } + else { - if (!activeAttribs[i] && attribs[i].mEnabled && attribs[i].mBoundBuffer != 0 && !mContext->getBuffer(attribs[i].mBoundBuffer)) - return GL_INVALID_OPERATION; + input = static_cast(attribute.mPointer); } - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + input += inputStride * start; + + if (converter.identity && inputStride == elementSize) { - translated[i].enabled = activeAttribs[i]; + memcpy(output, input, count * inputStride); } + else + { + converter.convertArray(input, inputStride, count, output); + } + + vertexBuffer->unmap(); - bool usesCurrentValues = false; + 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++) { - if (activeAttribs[i] && !attribs[i].mEnabled) + Buffer *buffer = attribs[i].mBoundBuffer.get(); + + if (translated[i].active && attribs[i].mArrayEnabled && (buffer || attribs[i].mPointer)) { - usesCurrentValues = true; - break; + 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)); + } + } } } - // Handle the identity-mapped attributes. - // Process array attributes. - - std::size_t requiredSpace = 0; - + // Invalidate static buffers if the attribute formats no longer match for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) { - if (activeAttribs[i] && attribs[i].mEnabled) + Buffer *buffer = attribs[i].mBoundBuffer.get(); + + if (translated[i].active && attribs[i].mArrayEnabled && buffer) { - requiredSpace += spaceRequired(attribs[i], count); + 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(); + } + } } } - if (requiredSpace > mStreamBuffer->size()) + // Reserve the required space per used buffer + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) { - std::size_t newSize = std::max(requiredSpace, 3 * mStreamBuffer->size() / 2); // 1.5 x mStreamBuffer->size() is arbitrary and should be checked to see we don't have too many reallocations. + Buffer *buffer = attribs[i].mBoundBuffer.get(); - TranslatedVertexBuffer *newStreamBuffer = mBackend->createVertexBuffer(newSize); + if (translated[i].active && attribs[i].mArrayEnabled && (buffer || attribs[i].mPointer)) + { + ArrayVertexBuffer *staticBuffer = buffer ? buffer->getVertexBuffer() : NULL; + ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : mStreamingBuffer; - delete mStreamBuffer; - mStreamBuffer = newStreamBuffer; + if (vertexBuffer) + { + vertexBuffer->reserveRequiredSpace(); + } + } } - mStreamBuffer->reserveSpace(requiredSpace); - - for (size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++) + // Perform the vertex data translations + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) { - if (activeAttribs[i] && attribs[i].mEnabled) + if (translated[i].active) { - FormatConverter formatConverter = mBackend->getFormatConverter(attribs[i].mType, attribs[i].mSize, attribs[i].mNormalized); + Buffer *buffer = attribs[i].mBoundBuffer.get(); - translated[i].nonArray = false; - translated[i].type = attribs[i].mType; - translated[i].size = attribs[i].mSize; - translated[i].normalized = attribs[i].mNormalized; - translated[i].stride = formatConverter.outputVertexSize; - translated[i].buffer = mStreamBuffer; + 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; + } - size_t inputStride = interpretGlStride(attribs[i]); - size_t elementSize = typeSize(attribs[i].mType) * attribs[i].mSize; + const FormatConverter &converter = formatConverter(attribs[i]); - void *output = mStreamBuffer->map(spaceRequired(attribs[i], count), &translated[i].offset); + StaticVertexBuffer *staticBuffer = buffer ? buffer->getVertexBuffer() : NULL; + ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : static_cast(mStreamingBuffer); - const void *input; - if (attribs[i].mBoundBuffer) - { - Buffer *buffer = mContext->getBuffer(attribs[i].mBoundBuffer); + UINT streamOffset = -1; + + if (staticBuffer) + { + streamOffset = staticBuffer->lookupAttribute(attribs[i]); - size_t offset = reinterpret_cast(attribs[i].mPointer); + if (streamOffset == -1) + { + // Convert the entire buffer + int totalCount = buffer->size() / attribs[i].stride(); + int startIndex = attribs[i].mOffset / attribs[i].stride(); - // Before we calculate the required size below, make sure it can be computed without integer overflow. - if (std::numeric_limits::max() - start < static_cast(count) - || std::numeric_limits::max() / inputStride < static_cast(start + count - 1) // it's a prerequisite that count >= 1, so start+count-1 >= 0. - || std::numeric_limits::max() - offset < inputStride * (start + count - 1) - || std::numeric_limits::max() - elementSize < offset + inputStride * (start + count - 1) + elementSize) + streamOffset = writeAttributeData(staticBuffer, -startIndex, totalCount, attribs[i]); + } + + if (streamOffset != -1) + { + streamOffset += (start + attribs[i].mOffset / attribs[i].stride()) * converter.outputElementSize; + } + } + else { - mStreamBuffer->unmap(); - return GL_INVALID_OPERATION; + streamOffset = writeAttributeData(mStreamingBuffer, start, count, attribs[i]); } - if (offset + inputStride * (start + count - 1) + elementSize > buffer->size()) + if (streamOffset == -1) { - mStreamBuffer->unmap(); - return GL_INVALID_OPERATION; + return GL_OUT_OF_MEMORY; } - input = static_cast(buffer->data()) + offset; + translated[i].vertexBuffer = vertexBuffer->getBuffer(); + translated[i].type = converter.d3dDeclType; + translated[i].stride = converter.outputElementSize; + translated[i].offset = streamOffset; } else { - input = attribs[i].mPointer; - } + 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; + } - input = static_cast(input) + inputStride * start; + translated[i].vertexBuffer = mCurrentValueBuffer[i]->getBuffer(); - if (formatConverter.identity && inputStride == elementSize) - { - memcpy(output, input, count * inputStride); + translated[i].type = D3DDECLTYPE_FLOAT4; + translated[i].stride = 0; + translated[i].offset = 0; } - else + } + } + + 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 struct GLToCType { }; + +template <> struct GLToCType { typedef GLbyte type; }; +template <> struct GLToCType { typedef GLubyte type; }; +template <> struct GLToCType { typedef GLshort type; }; +template <> struct GLToCType { typedef GLushort type; }; +template <> struct GLToCType { typedef GLuint type; }; +template <> struct GLToCType { 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 struct D3DToCType { }; + +template <> struct D3DToCType { typedef float type; }; +template <> struct D3DToCType { typedef short type; }; +template <> struct D3DToCType { typedef short type; }; +template <> struct D3DToCType { typedef unsigned char type; }; +template <> struct D3DToCType { typedef unsigned char type; }; +template <> struct D3DToCType { 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 +struct WidenRule +{ +}; + +template struct WidenRule : gl::NoWiden { }; +template struct WidenRule : gl::WidenToEven { }; +template struct WidenRule : gl::WidenToEven { }; +template struct WidenRule : gl::WidenToFour { }; +template struct WidenRule : gl::WidenToFour { }; +template struct WidenRule : gl::WidenToEven { }; + +// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination. +template +struct VertexTypeFlags +{ +}; + +template +struct VertexTypeFlagsHelper +{ + enum { capflag = capflag }; + enum { declflag = declflag }; +}; + +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; + + +// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums). +template +struct VertexTypeMapping +{ +}; + +template +struct VertexTypeMappingBase +{ + enum { preferred = Preferred }; + enum { fallback = Fallback }; +}; + +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Normalize +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity, Cast +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity, Normalize +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast, Normalize +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast, Normalize +template struct VertexTypeMapping : VertexTypeMappingBase { }; // FixedToFloat +template struct VertexTypeMapping : VertexTypeMappingBase { }; // 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 knows it's an identity mapping). +template +struct ConversionRule : gl::Cast::type, typename D3DToCType::type> +{ +}; + +// All conversions from normalized types to float use the Normalize operator. +template struct ConversionRule : gl::Normalize::type> { }; + +// Use a full specialisation for this so that it preferentially matches ahead of the generic normalize-to-float rules. +template <> struct ConversionRule : gl::FixedToFloat { }; +template <> struct ConversionRule : gl::FixedToFloat { }; + +// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1) +// whether it is normalized or not. +template +struct DefaultVertexValuesStage2 +{ +}; + +template struct DefaultVertexValuesStage2 : gl::NormalizedDefaultValues { }; +template struct DefaultVertexValuesStage2 : gl::SimpleDefaultValues { }; + +// Work out the default value rule for a D3D type (expressed as the C type) and +template +struct DefaultVertexValues : DefaultVertexValuesStage2 +{ +}; + +template struct DefaultVertexValues : gl::SimpleDefaultValues { }; + +// 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 struct UsePreferred { enum { type = T::preferred }; }; +template 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 class PreferenceRule> +struct Converter + : gl::VertexDataConverter::type, + WidenRule >::type, size>, + ConversionRule >::type>, + DefaultVertexValues >::type>::type, normalized > > +{ +private: + enum { d3dtype = PreferenceRule< VertexTypeMapping >::type }; + enum { d3dsize = WidenRule::finalWidth }; + +public: + enum { capflag = VertexTypeFlags::capflag }; + enum { declflag = VertexTypeFlags::declflag }; +}; + +// Initialise a TranslationInfo +#define TRANSLATION(type, norm, size, preferred) \ + { \ + Converter::identity, \ + Converter::finalSize, \ + Converter::convertArray, \ + static_cast(Converter::declflag) \ + } + +#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \ + { \ + Converter::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++) { - formatConverter.convertArray(input, inputStride, count, output); + 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]; - mStreamBuffer->unmap(); + 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++; } } - if (usesCurrentValues) + 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) { - processNonArrayAttributes(attribs, activeAttribs, translated, count); + 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); + } } +} - return GL_NO_ERROR; +VertexBuffer::~VertexBuffer() +{ + if (mVertexBuffer) + { + mVertexBuffer->Release(); + } } -std::size_t VertexDataManager::typeSize(GLenum type) const +void VertexBuffer::unmap() { - switch (type) + if (mVertexBuffer) { - case GL_BYTE: case GL_UNSIGNED_BYTE: return sizeof(GLbyte); - case GL_SHORT: case GL_UNSIGNED_SHORT: return sizeof(GLshort); - case GL_FIXED: return sizeof(GLfixed); - case GL_FLOAT: return sizeof(GLfloat); - default: UNREACHABLE(); return sizeof(GLfloat); + mVertexBuffer->Unlock(); } } -std::size_t VertexDataManager::interpretGlStride(const AttributeState &attrib) const +IDirect3DVertexBuffer9 *VertexBuffer::getBuffer() const { - return attrib.mStride ? attrib.mStride : typeSize(attrib.mType) * attrib.mSize; + return mVertexBuffer; } -// Round up x (>=0) to the next multiple of multiple (>0). -// 0 rounds up to 0. -std::size_t VertexDataManager::roundUp(std::size_t x, std::size_t multiple) const +ConstantVertexBuffer::ConstantVertexBuffer(IDirect3DDevice9 *device, float x, float y, float z, float w) : VertexBuffer(device, 4 * sizeof(float), D3DUSAGE_WRITEONLY) { - ASSERT(x >= 0); - ASSERT(multiple > 0); + void *buffer = NULL; - std::size_t remainder = x % multiple; - if (remainder != 0) + if (mVertexBuffer) { - return x + multiple - remainder; + HRESULT result = mVertexBuffer->Lock(0, 0, &buffer, 0); + + if (FAILED(result)) + { + ERR("Lock failed with error 0x%08x", result); + } } - else + + if (buffer) { - return x; + float *vector = (float*)buffer; + + vector[0] = x; + vector[1] = y; + vector[2] = z; + vector[3] = w; + + mVertexBuffer->Unlock(); } } -std::size_t VertexDataManager::spaceRequired(const AttributeState &attrib, std::size_t maxVertex) const +ConstantVertexBuffer::~ConstantVertexBuffer() { - std::size_t size = mBackend->getFormatConverter(attrib.mType, attrib.mSize, attrib.mNormalized).outputVertexSize; - size *= maxVertex; +} - return roundUp(size, 4 * sizeof(GLfloat)); +ArrayVertexBuffer::ArrayVertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags) : VertexBuffer(device, size, usageFlags) +{ + mBufferSize = size; + mWritePosition = 0; + mRequiredSpace = 0; } -void VertexDataManager::processNonArrayAttributes(const AttributeState *attribs, const std::bitset &activeAttribs, TranslatedAttribute *translated, std::size_t count) +ArrayVertexBuffer::~ArrayVertexBuffer() { - if (mDirtyCurrentValues) +} + +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) { - std::size_t totalSize = 4 * sizeof(float) * MAX_VERTEX_ATTRIBS; + 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; + } - mCurrentValueBuffer->reserveSpace(totalSize); + mRequiredSpace = 0; +} + +StaticVertexBuffer::StaticVertexBuffer(IDirect3DDevice9 *device) : ArrayVertexBuffer(device, 0, D3DUSAGE_WRITEONLY) +{ +} + +StaticVertexBuffer::~StaticVertexBuffer() +{ +} - float* currentValues = static_cast(mCurrentValueBuffer->map(totalSize, &mCurrentValueOffset)); +void *StaticVertexBuffer::map(const VertexAttribute &attribute, std::size_t requiredSpace, UINT *streamOffset) +{ + void *mapPtr = NULL; - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + if (mVertexBuffer) + { + HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, 0); + + if (FAILED(result)) { - // This assumes that the GL_FLOATx4 is supported by the back-end. (For D3D9, it is a mandatory format.) - currentValues[i*4+0] = attribs[i].mCurrentValue[0]; - currentValues[i*4+1] = attribs[i].mCurrentValue[1]; - currentValues[i*4+2] = attribs[i].mCurrentValue[2]; - currentValues[i*4+3] = attribs[i].mCurrentValue[3]; + ERR("Lock failed with error 0x%08x", result); + return NULL; } - mCurrentValueBuffer->unmap(); + int attributeOffset = attribute.mOffset % attribute.stride(); + VertexElement element = {attribute.mType, attribute.mSize, attribute.mNormalized, attributeOffset, mWritePosition}; + mCache.push_back(element); + + *streamOffset = mWritePosition; + mWritePosition += requiredSpace; } - for (std::size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++) + return mapPtr; +} + +void StaticVertexBuffer::reserveRequiredSpace() +{ + if (!mVertexBuffer && mBufferSize == 0) { - if (activeAttribs[i] && !attribs[i].mEnabled) + D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_WRITEONLY); + HRESULT result = mDevice->CreateVertexBuffer(mRequiredSpace, D3DUSAGE_WRITEONLY, 0, pool, &mVertexBuffer, NULL); + + if (FAILED(result)) { - translated[i].nonArray = true; + ERR("Out of memory allocating a vertex buffer of size %lu.", mRequiredSpace); + } - translated[i].buffer = mCurrentValueBuffer; + mBufferSize = mRequiredSpace; + } + else if (mVertexBuffer && mBufferSize >= mRequiredSpace) + { + // Already allocated + } + else UNREACHABLE(); // Static vertex buffers can't be resized - translated[i].type = GL_FLOAT; - translated[i].size = 4; - translated[i].normalized = false; - translated[i].stride = 0; - translated[i].offset = mCurrentValueOffset + 4 * sizeof(float) * i; + 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 index 04900b8..257f2c3 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.h +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/VertexDataManager.h @@ -10,7 +10,7 @@ #ifndef LIBGLESV2_GEOMETRY_VERTEXDATAMANAGER_H_ #define LIBGLESV2_GEOMETRY_VERTEXDATAMANAGER_H_ -#include +#include #include #define GL_APICALL @@ -21,44 +21,148 @@ namespace gl { -class Buffer; -class BufferBackEnd; -class TranslatedVertexBuffer; -struct TranslatedAttribute; -struct FormatConverter; -struct TranslatedIndexData; +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 mCache; +}; class VertexDataManager { public: - VertexDataManager(Context *context, BufferBackEnd *backend); - ~VertexDataManager(); + VertexDataManager(Context *context, IDirect3DDevice9 *backend); + virtual ~VertexDataManager(); - void dirtyCurrentValues() { mDirtyCurrentValues = true; } + void dirtyCurrentValue(int index) { mDirtyCurrentValue[index] = true; } - GLenum preRenderValidate(GLint start, - GLsizei count, - TranslatedAttribute *outAttribs); + void setupAttributes(const TranslatedAttribute *attributes); + GLenum prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *outAttribs); private: - std::bitset getActiveAttribs() const; + 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; + }; - void processNonArrayAttributes(const AttributeState *attribs, const std::bitset &activeAttribs, TranslatedAttribute *translated, std::size_t count); + enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; - std::size_t typeSize(GLenum type) const; - std::size_t interpretGlStride(const AttributeState &attrib) const; + FormatConverter mAttributeTypes[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1] - std::size_t roundUp(std::size_t x, std::size_t multiple) const; - std::size_t spaceRequired(const AttributeState &attrib, std::size_t maxVertex) const; + struct TranslationDescription + { + DWORD capsFlag; + FormatConverter preferredConversion; + FormatConverter fallbackConversion; + }; - Context *mContext; - BufferBackEnd *mBackend; + // 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] - TranslatedVertexBuffer *mStreamBuffer; + void checkVertexCaps(DWORD declTypes); - bool mDirtyCurrentValues; - std::size_t mCurrentValueOffset; // Offset within mCurrentValueBuffer that the current attribute values were last loaded at. - TranslatedVertexBuffer *mCurrentValueBuffer; + unsigned int typeIndex(GLenum type) const; + const FormatConverter &formatConverter(const VertexAttribute &attribute) const; }; } diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/backend.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/backend.cpp deleted file mode 100644 index 3f5e283..0000000 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/backend.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// geometry/backend.h: Abstract classes BufferBackEnd, TranslatedVertexBuffer and TranslatedIndexBuffer -// that must be implemented by any API-specific implementation of ANGLE. - -#include "libGLESv2/geometry/backend.h" - -#include "common/debug.h" - -namespace gl -{ - -void *TranslatedBuffer::map(std::size_t requiredSpace, std::size_t *offset) -{ - ASSERT(requiredSpace <= mBufferSize); - - reserveSpace(requiredSpace); - - *offset = mCurrentPoint; - mCurrentPoint += requiredSpace; - - return streamingMap(*offset, requiredSpace); -} - -void TranslatedBuffer::reserveSpace(std::size_t requiredSpace) -{ - if (mCurrentPoint + requiredSpace > mBufferSize) - { - recycle(); - mCurrentPoint = 0; - } -} - -} diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/backend.h b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/backend.h deleted file mode 100644 index d18a908..0000000 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/backend.h +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// geometry/backend.h: Abstract classes BufferBackEnd, TranslatedVertexBuffer and TranslatedIndexBuffer -// that must be implemented by any API-specific implementation of ANGLE. - -#ifndef LIBGLESV2_GEOMETRY_BACKEND_H_ -#define LIBGLESV2_GEOMETRY_BACKEND_H_ - -#include - -#define GL_APICALL -#include - -#include "libGLESv2/Context.h" - -namespace gl -{ -class TranslatedVertexBuffer; -class TranslatedIndexBuffer; - -struct FormatConverter -{ - bool identity; - std::size_t outputVertexSize; - void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out); -}; - -struct TranslatedAttribute -{ - bool enabled; - bool nonArray; - - // These are the original untranslated values. (Or just have some sort of BufferBackEnd::TranslatedTypeKey.) - GLenum type; - std::size_t size; - bool normalized; - - std::size_t offset; - - std::size_t stride; // 0 means not to advance the read pointer at all - - std::size_t semanticIndex; - - TranslatedVertexBuffer *buffer; -}; - -class BufferBackEnd -{ - public: - virtual ~BufferBackEnd() { } - - virtual bool supportIntIndices() = 0; - - virtual TranslatedVertexBuffer *createVertexBuffer(std::size_t size) = 0; - virtual TranslatedVertexBuffer *createVertexBufferForStrideZero(std::size_t size) = 0; - virtual TranslatedIndexBuffer *createIndexBuffer(std::size_t size, GLenum type) = 0; - virtual FormatConverter getFormatConverter(GLenum type, std::size_t size, bool normalize) = 0; - - // For an identity-mappable stream, verify that the stride and offset are okay. - virtual bool validateStream(GLenum type, std::size_t size, std::size_t stride, std::size_t offset) const = 0; - - virtual GLenum setupIndicesPreDraw(const TranslatedIndexData &indexInfo) = 0; - virtual GLenum setupAttributesPreDraw(const TranslatedAttribute *attributes) = 0; -}; - -class TranslatedBuffer -{ - public: - explicit TranslatedBuffer(std::size_t size) : mBufferSize(size), mCurrentPoint(0) { } - virtual ~TranslatedBuffer() { } - - std::size_t size() const { return mBufferSize; } - - virtual void *map() = 0; - virtual void unmap() = 0; - - void reserveSpace(std::size_t requiredSpace); - - void *map(std::size_t requiredSpace, std::size_t *offset); - - protected: - virtual void recycle() = 0; - virtual void *streamingMap(std::size_t offset, std::size_t size) = 0; - - private: - std::size_t mBufferSize; - std::size_t mCurrentPoint; - - DISALLOW_COPY_AND_ASSIGN(TranslatedBuffer); -}; - -class TranslatedVertexBuffer : public TranslatedBuffer -{ - public: - explicit TranslatedVertexBuffer(std::size_t size) : TranslatedBuffer(size) { } -}; - -class TranslatedIndexBuffer : public TranslatedBuffer -{ - public: - explicit TranslatedIndexBuffer(std::size_t size) : TranslatedBuffer(size) { } -}; - -} - -#endif // LIBGLESV2_GEOMETRY_BACKEND_H_ diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/dx9.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/dx9.cpp deleted file mode 100644 index e51befb..0000000 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/dx9.cpp +++ /dev/null @@ -1,613 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// geometry/dx9.h: Direct3D 9-based implementation of BufferBackEnd, TranslatedVertexBuffer and TranslatedIndexBuffer. - -#include "libGLESv2/geometry/dx9.h" - -#include - -#define GL_APICALL -#include - -#include "common/debug.h" - -#include "libGLESv2/Context.h" -#include "libGLESv2/main.h" -#include "libGLESv2/geometry/vertexconversion.h" -#include "libGLESv2/geometry/IndexDataManager.h" - -namespace -{ -// Mapping from OpenGL-ES vertex attrib type to D3D decl type: -// -// BYTE SHORT (Cast) -// BYTE-norm FLOAT (Normalize) (can't be exactly represented as SHORT-norm) -// UNSIGNED_BYTE UBYTE4 (Identity) or SHORT (Cast) -// UNSIGNED_BYTE-norm UBYTE4N (Identity) or FLOAT (Normalize) -// SHORT SHORT (Identity) -// SHORT-norm SHORT-norm (Identity) or FLOAT (Normalize) -// UNSIGNED_SHORT FLOAT (Cast) -// UNSIGNED_SHORT-norm USHORT-norm (Identity) or FLOAT (Normalize) -// FIXED (not in WebGL) FLOAT (FixedToFloat) -// FLOAT FLOAT (Identity) - -// GLToCType maps from GL type (as GLenum) to the C typedef. -template struct GLToCType { }; - -template <> struct GLToCType { typedef GLbyte type; }; -template <> struct GLToCType { typedef GLubyte type; }; -template <> struct GLToCType { typedef GLshort type; }; -template <> struct GLToCType { typedef GLushort type; }; -template <> struct GLToCType { typedef GLuint type; }; -template <> struct GLToCType { 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 struct D3DToCType { }; - -template <> struct D3DToCType { typedef float type; }; -template <> struct D3DToCType { typedef short type; }; -template <> struct D3DToCType { typedef short type; }; -template <> struct D3DToCType { typedef unsigned char type; }; -template <> struct D3DToCType { typedef unsigned char type; }; -template <> struct D3DToCType { 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 -struct WidenRule -{ -}; - -template struct WidenRule : gl::NoWiden { }; -template struct WidenRule : gl::WidenToEven { }; -template struct WidenRule : gl::WidenToEven { }; -template struct WidenRule : gl::WidenToFour { }; -template struct WidenRule : gl::WidenToFour { }; -template struct WidenRule : gl::WidenToEven { }; - -// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination. -template -struct VertexTypeFlags -{ -}; - -template -struct VertexTypeFlagsHelper -{ - enum { capflag = capflag }; - enum { declflag = declflag }; -}; - -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; - - -// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums). -template -struct VertexTypeMapping -{ -}; - -template -struct VertexTypeMappingBase -{ - enum { preferred = Preferred }; - enum { fallback = Fallback }; -}; - -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Normalize -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity, Cast -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity, Normalize -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast, Normalize -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast, Normalize -template struct VertexTypeMapping : VertexTypeMappingBase { }; // FixedToFloat -template struct VertexTypeMapping : VertexTypeMappingBase { }; // 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 knows it's an identity mapping). -template -struct ConversionRule : gl::Cast::type, typename D3DToCType::type> -{ -}; - -// All conversions from normalized types to float use the Normalize operator. -template struct ConversionRule : gl::Normalize::type> { }; - -// Use a full specialisation for this so that it preferentially matches ahead of the generic normalize-to-float rules. -template <> struct ConversionRule : gl::FixedToFloat { }; -template <> struct ConversionRule : gl::FixedToFloat { }; - -// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1) -// whether it is normalized or not. -template -struct DefaultVertexValuesStage2 -{ -}; - -template struct DefaultVertexValuesStage2 : gl::NormalizedDefaultValues { }; -template struct DefaultVertexValuesStage2 : gl::SimpleDefaultValues { }; - -// Work out the default value rule for a D3D type (expressed as the C type) and -template -struct DefaultVertexValues : DefaultVertexValuesStage2 -{ -}; - -template struct DefaultVertexValues : gl::SimpleDefaultValues { }; - -// 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 struct UsePreferred { enum { type = T::preferred }; }; -template 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 class PreferenceRule> -struct Converter - : gl::VertexDataConverter::type, - WidenRule >::type, size>, - ConversionRule >::type>, - DefaultVertexValues >::type>::type, normalized > > -{ -private: - enum { d3dtype = PreferenceRule< VertexTypeMapping >::type }; - enum { d3dsize = WidenRule::finalWidth }; - -public: - enum { capflag = VertexTypeFlags::capflag }; - enum { declflag = VertexTypeFlags::declflag }; -}; - -} - -namespace gl -{ -Dx9BackEnd::Dx9BackEnd(Context *context, IDirect3DDevice9 *d3ddevice) - : mDevice(d3ddevice) -{ - mDevice->AddRef(); - - for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) - { - mAppliedAttribEnabled[i] = true; - mStreamFrequency[i] = STREAM_FREQUENCY_UNINSTANCED; - } - - mStreamFrequency[MAX_VERTEX_ATTRIBS] = STREAM_FREQUENCY_UNINSTANCED; - - D3DCAPS9 caps = context->getDeviceCaps(); - - IDirect3D9 *d3dObject; - mDevice->GetDirect3D(&d3dObject); - - D3DADAPTER_IDENTIFIER9 ident; - d3dObject->GetAdapterIdentifier(caps.AdapterOrdinal, 0, &ident); - d3dObject->Release(); - - // Instancing is mandatory for all HW with SM3 vertex shaders, but avoid hardware where it does not work. - mUseInstancingForStrideZero = (caps.VertexShaderVersion >= D3DVS_VERSION(3, 0) && ident.VendorId != 0x8086); - mSupportIntIndices = (caps.MaxVertexIndex >= (1 << 16)); - - checkVertexCaps(caps.DeclTypes); -} - -Dx9BackEnd::~Dx9BackEnd() -{ - mDevice->Release(); -} - -bool Dx9BackEnd::supportIntIndices() -{ - return mSupportIntIndices; -} - -// Initialise a TranslationInfo -#define TRANSLATION(type, norm, size, preferred) \ - { \ - { \ - Converter::identity, \ - Converter::finalSize, \ - Converter::convertArray, \ - }, \ - static_cast(Converter::declflag) \ - } - -#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \ - { \ - Converter::capflag, \ - TRANSLATION(type, norm, size, UsePreferred), \ - TRANSLATION(type, norm, size, UseFallback) \ - } - -#define TRANSLATIONS_FOR_TYPE(type) \ - { \ - { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ - { TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) }, \ - } - -const Dx9BackEnd::TranslationDescription Dx9BackEnd::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1] -{ - TRANSLATIONS_FOR_TYPE(GL_BYTE), - TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE), - TRANSLATIONS_FOR_TYPE(GL_SHORT), - TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT), - TRANSLATIONS_FOR_TYPE(GL_FIXED), - TRANSLATIONS_FOR_TYPE(GL_FLOAT) -}; - -void Dx9BackEnd::checkVertexCaps(DWORD declTypes) -{ - for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++) - { - for (unsigned int j = 0; j < 2; j++) - { - for (unsigned int k = 0; k < 4; k++) - { - if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0) - { - mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion; - } - else - { - mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion; - } - } - } - } -} - -TranslatedVertexBuffer *Dx9BackEnd::createVertexBuffer(std::size_t size) -{ - return new Dx9VertexBuffer(mDevice, size); -} - -TranslatedVertexBuffer *Dx9BackEnd::createVertexBufferForStrideZero(std::size_t size) -{ - if (mUseInstancingForStrideZero) - { - return new Dx9VertexBuffer(mDevice, size); - } - else - { - return new Dx9VertexBufferZeroStrideWorkaround(mDevice, size); - } -} - -TranslatedIndexBuffer *Dx9BackEnd::createIndexBuffer(std::size_t size, GLenum type) -{ - return new Dx9IndexBuffer(mDevice, size, type); -} - -// This is used to index mAttributeTypes and mPossibleTranslations. -unsigned int Dx9BackEnd::typeIndex(GLenum type) const -{ - switch (type) - { - case GL_BYTE: return 0; - case GL_UNSIGNED_BYTE: return 1; - case GL_SHORT: return 2; - case GL_UNSIGNED_SHORT: return 3; - case GL_FIXED: return 4; - case GL_FLOAT: return 5; - - default: UNREACHABLE(); return 5; - } -} - -FormatConverter Dx9BackEnd::getFormatConverter(GLenum type, std::size_t size, bool normalize) -{ - return mAttributeTypes[typeIndex(type)][normalize][size-1].formatConverter; -} - -D3DDECLTYPE Dx9BackEnd::mapAttributeType(GLenum type, std::size_t size, bool normalize) const -{ - return mAttributeTypes[typeIndex(type)][normalize][size-1].d3dDeclType; -} - -bool Dx9BackEnd::validateStream(GLenum type, std::size_t size, std::size_t stride, std::size_t offset) const -{ - // D3D9 requires the stream offset and stride to be a multiple of DWORD. - return (stride % sizeof(DWORD) == 0 && offset % sizeof(DWORD) == 0); -} - -IDirect3DVertexBuffer9 *Dx9BackEnd::getDxBuffer(TranslatedVertexBuffer *vb) const -{ - return vb ? static_cast(vb)->getBuffer() : NULL; -} - -IDirect3DIndexBuffer9 *Dx9BackEnd::getDxBuffer(TranslatedIndexBuffer *ib) const -{ - return ib ? static_cast(ib)->getBuffer() : NULL; -} - -GLenum Dx9BackEnd::setupIndicesPreDraw(const TranslatedIndexData &indexInfo) -{ - mDevice->SetIndices(getDxBuffer(indexInfo.buffer)); - return GL_NO_ERROR; -} - -GLenum Dx9BackEnd::setupAttributesPreDraw(const TranslatedAttribute *attributes) -{ - HRESULT hr; - - D3DVERTEXELEMENT9 elements[MAX_VERTEX_ATTRIBS+1]; - - D3DVERTEXELEMENT9 *nextElement = &elements[0]; - - for (BYTE i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if (attributes[i].enabled) - { - nextElement->Stream = i + 1; // Stream 0 is skipped because D3D does not permit it to be an instanced stream. - nextElement->Offset = 0; - nextElement->Type = static_cast(mapAttributeType(attributes[i].type, attributes[i].size, attributes[i].normalized)); - nextElement->Method = D3DDECLMETHOD_DEFAULT; - nextElement->Usage = D3DDECLUSAGE_TEXCOORD; - nextElement->UsageIndex = attributes[i].semanticIndex; - nextElement++; - } - } - - static const D3DVERTEXELEMENT9 end = D3DDECL_END(); - *nextElement = end; - - IDirect3DVertexDeclaration9* vertexDeclaration; - hr = mDevice->CreateVertexDeclaration(elements, &vertexDeclaration); - mDevice->SetVertexDeclaration(vertexDeclaration); - vertexDeclaration->Release(); - - mDevice->SetStreamSource(0, NULL, 0, 0); - - bool nonArrayAttributes = false; - - for (size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if (attributes[i].enabled) - { - if (attributes[i].nonArray) nonArrayAttributes = true; - - mDevice->SetStreamSource(i + 1, getDxBuffer(attributes[i].buffer), attributes[i].offset, attributes[i].stride); - if (!mAppliedAttribEnabled[i]) - { - mAppliedAttribEnabled[i] = true; - } - } - else - { - if (mAppliedAttribEnabled[i]) - { - mDevice->SetStreamSource(i + 1, 0, 0, 0); - mAppliedAttribEnabled[i] = false; - } - } - } - - if (mUseInstancingForStrideZero) - { - // When there are no stride zero attributes, we disable instancing so that DrawPrimitive can be used. - - if (nonArrayAttributes) - { - if (mStreamFrequency[0] != STREAM_FREQUENCY_INDEXED) - { - mStreamFrequency[0] = STREAM_FREQUENCY_INDEXED; - mDevice->SetStreamSourceFreq(0, D3DSTREAMSOURCE_INDEXEDDATA | 1); - } - - for (size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if (attributes[i].enabled) - { - if (attributes[i].nonArray) - { - if (mStreamFrequency[i+1] != STREAM_FREQUENCY_INSTANCED) - { - mStreamFrequency[i+1] = STREAM_FREQUENCY_INSTANCED; - mDevice->SetStreamSourceFreq(i + 1, D3DSTREAMSOURCE_INSTANCEDATA | 1); - } - } - else - { - if (mStreamFrequency[i+1] != STREAM_FREQUENCY_INDEXED) - { - mStreamFrequency[i+1] = STREAM_FREQUENCY_INDEXED; - mDevice->SetStreamSourceFreq(i + 1, D3DSTREAMSOURCE_INDEXEDDATA | 1); - } - } - } - } - } - else - { - for (size_t i = 0; i < MAX_VERTEX_ATTRIBS + 1; i++) - { - if (mStreamFrequency[i] != STREAM_FREQUENCY_UNINSTANCED) - { - mStreamFrequency[i] = STREAM_FREQUENCY_UNINSTANCED; - - // This should not be needed, but otherwise there is a buggy driver that will leave instancing - // enabled for the first draw after it has been turned off. - mDevice->SetStreamSourceFreq(i, D3DSTREAMSOURCE_INDEXEDDATA | 1); - - mDevice->SetStreamSourceFreq(i, 1); - } - } - } - } - - return GL_NO_ERROR; -} - -Dx9BackEnd::Dx9VertexBuffer::Dx9VertexBuffer(IDirect3DDevice9 *device, std::size_t size) - : TranslatedVertexBuffer(size) -{ - HRESULT hr = device->CreateVertexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mVertexBuffer, NULL); - if (hr != S_OK) - { - ERR("Out of memory allocating a vertex buffer of size %lu.", size); - throw std::bad_alloc(); - } -} - -Dx9BackEnd::Dx9VertexBuffer::Dx9VertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags) - : TranslatedVertexBuffer(size) -{ - HRESULT hr = device->CreateVertexBuffer(size, usageFlags, 0, D3DPOOL_DEFAULT, &mVertexBuffer, NULL); - if (hr != S_OK) - { - ERR("Out of memory allocating a vertex buffer of size %lu.", size); - throw std::bad_alloc(); - } -} - - -Dx9BackEnd::Dx9VertexBuffer::~Dx9VertexBuffer() -{ - mVertexBuffer->Release(); -} - -IDirect3DVertexBuffer9 *Dx9BackEnd::Dx9VertexBuffer::getBuffer() const -{ - return mVertexBuffer; -} - -void *Dx9BackEnd::Dx9VertexBuffer::map() -{ - void *mapPtr; - - mVertexBuffer->Lock(0, 0, &mapPtr, 0); - - return mapPtr; -} - -void Dx9BackEnd::Dx9VertexBuffer::unmap() -{ - mVertexBuffer->Unlock(); -} - -void Dx9BackEnd::Dx9VertexBuffer::recycle() -{ - void *dummy; - mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); - mVertexBuffer->Unlock(); -} - -void *Dx9BackEnd::Dx9VertexBuffer::streamingMap(std::size_t offset, std::size_t size) -{ - void *mapPtr; - - mVertexBuffer->Lock(offset, size, &mapPtr, D3DLOCK_NOOVERWRITE); - - return mapPtr; -} - -// Normally VBs are created with D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, but some hardware & drivers won't render -// if any stride-zero streams are in D3DUSAGE_DYNAMIC VBs, so this provides a way to create such VBs with only D3DUSAGE_WRITEONLY set. -// D3DLOCK_DISCARD and D3DLOCK_NOOVERWRITE are only available on D3DUSAGE_DYNAMIC VBs, so we override methods to avoid using these flags. -Dx9BackEnd::Dx9VertexBufferZeroStrideWorkaround::Dx9VertexBufferZeroStrideWorkaround(IDirect3DDevice9 *device, std::size_t size) - : Dx9VertexBuffer(device, size, D3DUSAGE_WRITEONLY) -{ -} - -void Dx9BackEnd::Dx9VertexBufferZeroStrideWorkaround::recycle() -{ -} - -void *Dx9BackEnd::Dx9VertexBufferZeroStrideWorkaround::streamingMap(std::size_t offset, std::size_t size) -{ - void *mapPtr; - - getBuffer()->Lock(offset, size, &mapPtr, 0); - - return mapPtr; -} - -Dx9BackEnd::Dx9IndexBuffer::Dx9IndexBuffer(IDirect3DDevice9 *device, std::size_t size, GLenum type) - : TranslatedIndexBuffer(size) -{ - ASSERT(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT); - - D3DFORMAT format = (type == GL_UNSIGNED_SHORT) ? D3DFMT_INDEX16 : D3DFMT_INDEX32; - - HRESULT hr = device->CreateIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, D3DPOOL_DEFAULT, &mIndexBuffer, NULL); - if (hr != S_OK) - { - ERR("Out of memory allocating an index buffer of size %lu.", size); - throw std::bad_alloc(); - } -} - -Dx9BackEnd::Dx9IndexBuffer::~Dx9IndexBuffer() -{ - mIndexBuffer->Release(); -} - -IDirect3DIndexBuffer9*Dx9BackEnd::Dx9IndexBuffer::getBuffer() const -{ - return mIndexBuffer; -} - -void *Dx9BackEnd::Dx9IndexBuffer::map() -{ - void *mapPtr; - - mIndexBuffer->Lock(0, 0, &mapPtr, 0); - - return mapPtr; -} - -void Dx9BackEnd::Dx9IndexBuffer::unmap() -{ - mIndexBuffer->Unlock(); -} - -void Dx9BackEnd::Dx9IndexBuffer::recycle() -{ - void *dummy; - mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); - mIndexBuffer->Unlock(); -} - -void *Dx9BackEnd::Dx9IndexBuffer::streamingMap(std::size_t offset, std::size_t size) -{ - void *mapPtr; - - mIndexBuffer->Lock(offset, size, &mapPtr, D3DLOCK_NOOVERWRITE); - - return mapPtr; -} - -} diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/dx9.h b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/dx9.h deleted file mode 100644 index 6068dd6..0000000 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/dx9.h +++ /dev/null @@ -1,137 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// geometry/dx9.h: Direct3D 9-based implementation of BufferBackEnd, TranslatedVertexBuffer and TranslatedIndexBuffer. - -#ifndef LIBGLESV2_GEOMETRY_DX9_H_ -#define LIBGLESV2_GEOMETRY_DX9_H_ - -#include - -#include "libGLESv2/Buffer.h" -#include "libGLESv2/geometry/backend.h" - -namespace gl -{ - -class Dx9BackEnd : public BufferBackEnd -{ - public: - explicit Dx9BackEnd(Context *context, IDirect3DDevice9 *d3ddevice); - ~Dx9BackEnd(); - - virtual bool supportIntIndices(); - - virtual TranslatedVertexBuffer *createVertexBuffer(std::size_t size); - virtual TranslatedVertexBuffer *createVertexBufferForStrideZero(std::size_t size); - virtual TranslatedIndexBuffer *createIndexBuffer(std::size_t size, GLenum type); - virtual FormatConverter getFormatConverter(GLenum type, std::size_t size, bool normalize); - - virtual bool validateStream(GLenum type, std::size_t size, std::size_t stride, std::size_t offset) const; - - virtual GLenum setupIndicesPreDraw(const TranslatedIndexData &indexInfo); - virtual GLenum setupAttributesPreDraw(const TranslatedAttribute *attributes); - - private: - IDirect3DDevice9 *mDevice; - - bool mUseInstancingForStrideZero; - bool mSupportIntIndices; - - bool mAppliedAttribEnabled[MAX_VERTEX_ATTRIBS]; - - enum StreamFrequency - { - STREAM_FREQUENCY_UNINSTANCED = 0, - STREAM_FREQUENCY_INDEXED, - STREAM_FREQUENCY_INSTANCED - }; - - StreamFrequency mStreamFrequency[MAX_VERTEX_ATTRIBS+1]; - - struct TranslationInfo - { - FormatConverter formatConverter; - D3DDECLTYPE d3dDeclType; - }; - - enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; - - TranslationInfo mAttributeTypes[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size-1] - - struct TranslationDescription - { - DWORD capsFlag; - TranslationInfo preferredConversion; - TranslationInfo fallbackConversion; - }; - - // This table is used to generate mAttributeTypes. - static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size-1] - - void checkVertexCaps(DWORD declTypes); - - unsigned int typeIndex(GLenum type) const; - - class Dx9VertexBuffer : public TranslatedVertexBuffer - { - public: - Dx9VertexBuffer(IDirect3DDevice9 *device, std::size_t size); - virtual ~Dx9VertexBuffer(); - - IDirect3DVertexBuffer9 *getBuffer() const; - - protected: - Dx9VertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags); - - virtual void *map(); - virtual void unmap(); - - virtual void recycle(); - virtual void *streamingMap(std::size_t offset, std::size_t size); - - private: - IDirect3DVertexBuffer9 *mVertexBuffer; - }; - - class Dx9VertexBufferZeroStrideWorkaround : public Dx9VertexBuffer - { - public: - Dx9VertexBufferZeroStrideWorkaround(IDirect3DDevice9 *device, std::size_t size); - - protected: - virtual void recycle(); - virtual void *streamingMap(std::size_t offset, std::size_t size); - }; - - class Dx9IndexBuffer : public TranslatedIndexBuffer - { - public: - Dx9IndexBuffer(IDirect3DDevice9 *device, std::size_t size, GLenum type); - virtual ~Dx9IndexBuffer(); - - IDirect3DIndexBuffer9 *getBuffer() const; - - protected: - virtual void *map(); - virtual void unmap(); - - virtual void recycle(); - virtual void *streamingMap(std::size_t offset, std::size_t size); - - private: - IDirect3DIndexBuffer9 *mIndexBuffer; - }; - - IDirect3DVertexBuffer9 *getDxBuffer(TranslatedVertexBuffer *vb) const; - IDirect3DIndexBuffer9 *getDxBuffer(TranslatedIndexBuffer *ib) const; - - D3DDECLTYPE mapAttributeType(GLenum type, std::size_t size, bool normalized) const; -}; - -} - -#endif // LIBGLESV2_GEOMETRY_DX9_H_ diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.cpp index 25d083b..543c0d2 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.cpp +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.cpp @@ -20,6 +20,7 @@ #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" @@ -736,7 +737,7 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna try { - if (level < 0 || level > gl::MAX_TEXTURE_LEVELS) + if (level < 0) { return error(GL_INVALID_VALUE); } @@ -746,34 +747,6 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna return error(GL_INVALID_VALUE); } - switch (target) - { - case GL_TEXTURE_2D: - if (width > (gl::MAX_TEXTURE_SIZE >> level) || height > (gl::MAX_TEXTURE_SIZE >> level)) - { - return error(GL_INVALID_VALUE); - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (width != height) - { - return error(GL_INVALID_VALUE); - } - - if (width > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level) || height > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level)) - { - return error(GL_INVALID_VALUE); - } - break; - default: - return error(GL_INVALID_ENUM); - } - switch (internalformat) { case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: @@ -792,6 +765,41 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna 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 @@ -859,7 +867,7 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs return error(GL_INVALID_ENUM); } - if (level < 0 || level > gl::MAX_TEXTURE_LEVELS) + if (level < 0) { return error(GL_INVALID_VALUE); } @@ -888,6 +896,11 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs 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. @@ -978,48 +991,6 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma return error(GL_INVALID_VALUE); } - switch (target) - { - case GL_TEXTURE_2D: - if (width > (gl::MAX_TEXTURE_SIZE >> level) || height > (gl::MAX_TEXTURE_SIZE >> level)) - { - return error(GL_INVALID_VALUE); - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (width != height) - { - return error(GL_INVALID_VALUE); - } - - if (width > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level) || height > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level)) - { - return error(GL_INVALID_VALUE); - } - break; - default: - return error(GL_INVALID_ENUM); - } - - switch (internalformat) - { - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - case GL_RGB: - case GL_RGBA: - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // Compressed textures are not supported here, but if they are unsupported altogether, - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: // a different error is generated than otherwise. That is handled below. - break; - default: - return error(GL_INVALID_VALUE); - } - if (border != 0) { return error(GL_INVALID_VALUE); @@ -1029,20 +1000,38 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma if (context) { - if (internalformat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || - internalformat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) + switch (target) { - if (context->supportsCompressedTextures()) + case GL_TEXTURE_2D: + if (width > (context->getMaximumTextureDimension() >> level) || + height > (context->getMaximumTextureDimension() >> level)) { - return error(GL_INVALID_OPERATION); + return error(GL_INVALID_VALUE); } - else + 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_ENUM); + 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); @@ -1054,6 +1043,59 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma } gl::Colorbuffer *source = framebuffer->getColorbuffer(); + GLenum colorbufferFormat = source->getFormat(); + + // [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(); @@ -1062,11 +1104,6 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma { return error(GL_INVALID_OPERATION); } - - if (texture->isCompressed()) - { - return error(GL_INVALID_OPERATION); - } texture->copyImage(level, internalformat, x, y, width, height, source); } @@ -1079,17 +1116,9 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma return error(GL_INVALID_OPERATION); } - if (texture->isCompressed()) - { - return error(GL_INVALID_OPERATION); - } - texture->copyImage(target, level, internalformat, x, y, width, height, source); } - else - { - UNREACHABLE(); - } + else UNREACHABLE(); } } catch(std::bad_alloc&) @@ -1111,7 +1140,7 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL return error(GL_INVALID_ENUM); } - if (level < 0 || level > gl::MAX_TEXTURE_LEVELS || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) + if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) { return error(GL_INVALID_VALUE); } @@ -1130,7 +1159,13 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL 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); @@ -1142,42 +1177,70 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL } gl::Colorbuffer *source = framebuffer->getColorbuffer(); + GLenum colorbufferFormat = source->getFormat(); + gl::Texture *texture = NULL; + if (target == GL_TEXTURE_2D) { - gl::Texture2D *texture = context->getTexture2D(); + texture = context->getTexture2D(); + } + else if (gl::IsCubemapTextureTarget(target)) + { + texture = context->getTextureCubeMap(); + } + else UNREACHABLE(); - if (!texture) - { - return error(GL_INVALID_OPERATION); - } + if (!texture) + { + return error(GL_INVALID_OPERATION); + } - if (texture->isCompressed()) + GLenum textureFormat = texture->getFormat(); + + // [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); } - - texture->copySubImage(level, xoffset, yoffset, x, y, width, height, source); - } - else if (gl::IsCubemapTextureTarget(target)) - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - - if (!texture) + 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); } - - if (texture->isCompressed()) + 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); } - - texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, source); - } - else - { - UNREACHABLE(); + 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, source); } } @@ -1293,6 +1356,33 @@ void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers) } } +void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences) +{ + TRACE("(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) { TRACE("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers); @@ -1624,7 +1714,7 @@ void __stdcall glDisableVertexAttribArray(GLuint index) if (context) { - context->setVertexAttribEnabled(index, false); + context->setEnableVertexAttribArray(index, false); } } catch(std::bad_alloc&) @@ -1669,20 +1759,25 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv return error(GL_INVALID_VALUE); } - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT: - case GL_UNSIGNED_INT: - break; - default: - return error(GL_INVALID_ENUM); - } - gl::Context *context = gl::getContext(); if (context) { + 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); } } @@ -1739,7 +1834,33 @@ void __stdcall glEnableVertexAttribArray(GLuint index) if (context) { - context->setVertexAttribEnabled(index, true); + context->setEnableVertexAttribArray(index, true); + } + } + catch(std::bad_alloc&) + { + return error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glFinishFenceNV(GLuint fence) +{ + TRACE("(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&) @@ -2046,6 +2167,33 @@ void __stdcall glGenerateMipmap(GLenum target) } } +void __stdcall glGenFencesNV(GLsizei n, GLuint* fences) +{ + TRACE("(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) { TRACE("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers); @@ -2421,6 +2569,33 @@ GLenum __stdcall glGetError(void) return GL_NO_ERROR; } +void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) +{ + TRACE("(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) { TRACE("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params); @@ -3287,12 +3462,12 @@ void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) return error(GL_INVALID_VALUE); } - const gl::AttributeState &attribState = context->getVertexAttribState(index); + const gl::VertexAttribute &attribState = context->getVertexAttribState(index); switch (pname) { case GL_VERTEX_ATTRIB_ARRAY_ENABLED: - *params = (GLfloat)(attribState.mEnabled ? GL_TRUE : GL_FALSE); + *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE); break; case GL_VERTEX_ATTRIB_ARRAY_SIZE: *params = (GLfloat)attribState.mSize; @@ -3340,12 +3515,12 @@ void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) return error(GL_INVALID_VALUE); } - const gl::AttributeState &attribState = context->getVertexAttribState(index); + const gl::VertexAttribute &attribState = context->getVertexAttribState(index); switch (pname) { case GL_VERTEX_ATTRIB_ARRAY_ENABLED: - *params = (attribState.mEnabled ? GL_TRUE : GL_FALSE); + *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE); break; case GL_VERTEX_ATTRIB_ARRAY_SIZE: *params = attribState.mSize; @@ -3414,28 +3589,27 @@ void __stdcall glHint(GLenum target, GLenum mode) try { - switch (target) + switch (mode) { - case GL_GENERATE_MIPMAP_HINT: - switch (mode) - { - case GL_FASTEST: - case GL_NICEST: - case GL_DONT_CARE: - break; - default: - return error(GL_INVALID_ENUM); - } + case GL_FASTEST: + case GL_NICEST: + case GL_DONT_CARE: break; default: - return error(GL_INVALID_ENUM); + return error(GL_INVALID_ENUM); } gl::Context *context = gl::getContext(); - if (context) + switch (target) { - if (target == GL_GENERATE_MIPMAP_HINT) - context->setGenerateMipmapHint(mode); + 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&) @@ -3504,6 +3678,34 @@ GLboolean __stdcall glIsEnabled(GLenum cap) return false; } +GLboolean __stdcall glIsFenceNV(GLuint fence) +{ + TRACE("(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) { TRACE("(GLuint framebuffer = %d)", framebuffer); @@ -3841,22 +4043,12 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp return error(GL_INVALID_ENUM); } - switch (internalformat) + if (!gl::IsColorRenderable(internalformat) && !gl::IsDepthRenderable(internalformat) && !gl::IsStencilRenderable(internalformat)) { - case GL_DEPTH_COMPONENT16: - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGB565: - case GL_STENCIL_INDEX8: - case GL_DEPTH24_STENCIL8_OES: - case GL_RGB8_OES: - case GL_RGBA8_OES: - break; - default: return error(GL_INVALID_ENUM); } - if (width < 0 || height < 0 || width > gl::MAX_RENDERBUFFER_SIZE || height > gl::MAX_RENDERBUFFER_SIZE || samples < 0) + if (width < 0 || height < 0 || samples < 0) { return error(GL_INVALID_VALUE); } @@ -3865,7 +4057,9 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp if (context) { - if (samples > context->getMaxSupportedSamples()) + if (width > context->getMaximumRenderbufferDimension() || + height > context->getMaximumRenderbufferDimension() || + samples > context->getMaxSupportedSamples()) { return error(GL_INVALID_VALUE); } @@ -3929,6 +4123,37 @@ void __stdcall glSampleCoverage(GLclampf value, GLboolean invert) } } +void __stdcall glSetFenceNV(GLuint fence, GLenum condition) +{ + TRACE("(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) { TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); @@ -4196,6 +4421,34 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu } } +GLboolean __stdcall glTestFenceNV(GLuint fence) +{ + TRACE("(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) { @@ -4215,34 +4468,6 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL return error(GL_INVALID_VALUE); } - switch (target) - { - case GL_TEXTURE_2D: - if (width > (gl::MAX_TEXTURE_SIZE >> level) || height > (gl::MAX_TEXTURE_SIZE >> level)) - { - return error(GL_INVALID_VALUE); - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (width != height) - { - return error(GL_INVALID_VALUE); - } - - if (width > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level) || height > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level)) - { - return error(GL_INVALID_VALUE); - } - break; - default: - return error(GL_INVALID_ENUM); - } - if (internalformat != format) { return error(GL_INVALID_OPERATION); @@ -4256,6 +4481,8 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL switch (type) { case GL_UNSIGNED_BYTE: + case GL_FLOAT: + case GL_HALF_FLOAT_OES: break; default: return error(GL_INVALID_ENUM); @@ -4266,6 +4493,8 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL { 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); @@ -4277,6 +4506,8 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL 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); @@ -4307,6 +4538,36 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL 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 (internalformat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || internalformat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) { @@ -4320,6 +4581,21 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL } } + 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(); @@ -4462,7 +4738,7 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint return error(GL_INVALID_ENUM); } - if (level < 0 || level > gl::MAX_TEXTURE_LEVELS || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) + if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) { return error(GL_INVALID_VALUE); } @@ -4486,6 +4762,26 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint 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(); @@ -4500,6 +4796,11 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint return error(GL_INVALID_OPERATION); } + if (format != texture->getFormat()) + { + return error(GL_INVALID_OPERATION); + } + texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels); } else if (gl::IsCubemapTextureTarget(target)) @@ -4516,6 +4817,11 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint return error(GL_INVALID_OPERATION); } + if (format != texture->getFormat()) + { + return error(GL_INVALID_OPERATION); + } + texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels); } else @@ -5435,6 +5741,14 @@ __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char * { {"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++) diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.def b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.def index a043ed8..b2dc23c 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.def +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.def @@ -147,7 +147,14 @@ EXPORTS 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 diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.vcproj b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.vcproj index 1f43e7a..0d95080 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.vcproj +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.vcproj @@ -201,6 +201,10 @@ > + + @@ -244,14 +248,6 @@ Name="Geometry" > - - - - @@ -279,6 +275,10 @@ > + + @@ -334,14 +334,6 @@ Name="Geometry" > - - - - diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.cpp index 7fc2bc4..a3f5243 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.cpp +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.cpp @@ -25,6 +25,8 @@ int UniformComponentCount(GLenum 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: @@ -68,6 +70,8 @@ GLenum UniformComponentType(GLenum type) 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: @@ -247,6 +251,28 @@ int ComputePixelSize(GLenum format, GLenum type) 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(); } @@ -283,6 +309,21 @@ bool CheckTextureFormatType(GLenum format, GLenum type) 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); @@ -295,6 +336,69 @@ bool CheckTextureFormatType(GLenum format, GLenum type) } } +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 @@ -508,6 +612,10 @@ 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: @@ -515,7 +623,6 @@ unsigned int GetAlphaSize(D3DFORMAT colorFormat) case D3DFMT_A1R5G5B5: return 1; case D3DFMT_X8R8G8B8: - case D3DFMT_X1R5G5B5: case D3DFMT_R5G6B5: return 0; default: UNREACHABLE(); @@ -527,6 +634,10 @@ 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: @@ -534,7 +645,6 @@ unsigned int GetRedSize(D3DFORMAT colorFormat) return 8; case D3DFMT_A1R5G5B5: case D3DFMT_R5G6B5: - case D3DFMT_X1R5G5B5: return 5; default: UNREACHABLE(); } @@ -545,13 +655,16 @@ 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: - case D3DFMT_X1R5G5B5: return 5; case D3DFMT_R5G6B5: return 6; @@ -564,6 +677,10 @@ 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: @@ -571,7 +688,6 @@ unsigned int GetBlueSize(D3DFORMAT colorFormat) return 8; case D3DFMT_A1R5G5B5: case D3DFMT_R5G6B5: - case D3DFMT_X1R5G5B5: return 5; default: UNREACHABLE(); } @@ -591,46 +707,46 @@ unsigned int GetDepthSize(D3DFORMAT depthFormat) 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 + //case D3DFMT_D32_LOCKABLE: return 32; // D3D9Ex only + //case D3DFMT_S8_LOCKABLE: return 0; // D3D9Ex only default: UNREACHABLE(); } return 0; } -bool ConvertPrimitiveType(GLenum primitiveType, GLsizei primitiveCount, +bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount) { switch (primitiveType) { case GL_POINTS: *d3dPrimitiveType = D3DPT_POINTLIST; - *d3dPrimitiveCount = primitiveCount; + *d3dPrimitiveCount = elementCount; break; case GL_LINES: *d3dPrimitiveType = D3DPT_LINELIST; - *d3dPrimitiveCount = primitiveCount / 2; + *d3dPrimitiveCount = elementCount / 2; break; case GL_LINE_LOOP: *d3dPrimitiveType = D3DPT_LINESTRIP; - *d3dPrimitiveCount = primitiveCount; + *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 = primitiveCount - 1; + *d3dPrimitiveCount = elementCount - 1; break; case GL_TRIANGLES: *d3dPrimitiveType = D3DPT_TRIANGLELIST; - *d3dPrimitiveCount = primitiveCount / 3; + *d3dPrimitiveCount = elementCount / 3; break; case GL_TRIANGLE_STRIP: *d3dPrimitiveType = D3DPT_TRIANGLESTRIP; - *d3dPrimitiveCount = primitiveCount - 2; + *d3dPrimitiveCount = elementCount - 2; break; case GL_TRIANGLE_FAN: *d3dPrimitiveType = D3DPT_TRIANGLEFAN; - *d3dPrimitiveCount = primitiveCount - 2; + *d3dPrimitiveCount = elementCount - 2; break; default: return false; @@ -672,3 +788,40 @@ D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples) } } + +namespace dx2es +{ + +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; +} + +} diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.h b/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.h index b6c8ce5..85e8f26 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.h +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.h @@ -36,6 +36,10 @@ 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 @@ -57,7 +61,7 @@ unsigned int GetGreenSize(D3DFORMAT colorFormat); unsigned int GetBlueSize(D3DFORMAT colorFormat); unsigned int GetDepthSize(D3DFORMAT depthFormat); unsigned int GetStencilSize(D3DFORMAT stencilFormat); -bool ConvertPrimitiveType(GLenum primitiveType, GLsizei primitiveCount, +bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount); D3DFORMAT ConvertRenderbufferFormat(GLenum format); D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples); @@ -65,4 +69,12 @@ GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type); } +namespace dx2es +{ + +GLenum ConvertBackBufferFormat(D3DFORMAT format); +GLenum ConvertDepthStencilFormat(D3DFORMAT format); + +} + #endif // LIBGLESV2_UTILITIES_H -- cgit v1.1