From a7d093e740b1e20874b5ebeb37b5c5d76ae19e42 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 24 Feb 2014 11:18:33 +0200 Subject: Upgrade ANGLE to 1.3.5bb7ec572d0a This brings Qt's copy of ANGLE up to ANGLE master, which contains a number of bugfixes as well as restructuring for the upcoming ES 3.0 support. This version brings considerable stability improvements to the D3D11 renderer. The static translator project files have been merged to align with the ANGLE source tree. Two new patches have been applied to fix errors in upstream ANGLE: - 0011-ANGLE-Fix-compilation-error-on-MinGW-caused-by-trace.patch The event trace header in ANGLE's third_party directory has an unused template which causes a compilation error on MinGW. Disable this part of the code. - 0012-ANGLE-fix-semantic-index-lookup.patch The sorted semantic index table was returning a direct mapping to the new indices, instead of the old indices. This caused a mismatch in the GL type lookup for the translated attribute. All other patches have been rebased, removed if no longer needed, and renamed to clear up the application order: - 0001-Fix-compilation-for-MSVC-2008-and-std-tuple.patch No changes. - 0001-Fix-compilation-with-MinGW-mingw-tdm64-gcc-4.8.1.patch No changes. Renamed to 0002. - 0001-Fix-compilation-with-MinGW-gcc-64-bit.patch No changes. Renamed to 0003. - 0001-Make-it-possible-to-link-ANGLE-statically-for-single.patch Modified patch to adapt to new DLL loading structure. Renamed to 0004. - 0005-Fix-build-when-SSE2-is-not-available.patch No changes. - 0011-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch No changes. Renamed to 0006. - 0006-Make-DX9-DX11-mutually-exclusive.patch Made the patch less invasive by allowing D3D9 code to run unless explicitly disabled (e.g. on WinRT, where it doesn't compile). This makes the patch smaller and allows Desktop Windows to compile both D3D9 and D3D11 codepaths. Renamed to 0007. - 0015-ANGLE-Dynamically-load-D3D-compiler-from-a-list-of-k.patch No changes. Renamed to 0008. - 0012-ANGLE-Support-WinRT.patch Made D3D11_level9 initialization only possible if D3D9 is disabled. This makes sure Desktop PCs use the old D3D9 codepath instead of the less-tested D3D11_level9 codepath. Renamed to 0009. - 0013-Enable-D3D11-for-feature-level-9-cards.patch Conveniently smaller patch due to buffer implementation improvements upstream. Renamed to 0010. - 0014-ANGLE-D3D11-Alwayls-execute-QueryInterface.patch This was a fix for patch 0009, so was integrated there. Removed. - 0016-ANGLE-D3D11-Fix-build-on-desktop-Windows.patch This was a fix for patch 0009, so it was integrated there. Removed. - 0001-ANGLE-Fix-compilation-with-MSVC2013.patch Fixed upstream. Removed. - 0007-ANGLE-Fix-typedefs-for-Win64.patch Fixed upstream. Removed. - 0004-Fix-black-screen-after-minimizing-OpenGL-window-with.patch The issue has been fixed in Qt itself. Removed. - 0008-DX11-Prevent-assert-when-view-is-minimized-or-.patch The cause of the problem was the same as patch 0004, but for the D3D11 codepath. Removed. Change-Id: Id69484ab3a3e013050741c462fb1b06dfb0fd112 Reviewed-by: Friedemann Kleint Reviewed-by: Kai Koehne Reviewed-by: Oliver Wolff --- src/3rdparty/angle/src/commit.h | 2 + src/3rdparty/angle/src/common/angleutils.h | 14 + src/3rdparty/angle/src/common/debug.cpp | 44 +- src/3rdparty/angle/src/common/debug.h | 32 +- src/3rdparty/angle/src/common/event_tracer.cpp | 2 +- src/3rdparty/angle/src/common/event_tracer.h | 12 +- src/3rdparty/angle/src/common/system.h | 26 - src/3rdparty/angle/src/common/version.h | 18 +- src/3rdparty/angle/src/compiler/BaseTypes.h | 148 - .../angle/src/compiler/BuiltInFunctionEmulator.cpp | 406 --- .../angle/src/compiler/BuiltInFunctionEmulator.h | 93 - src/3rdparty/angle/src/compiler/CodeGenGLSL.cpp | 34 - src/3rdparty/angle/src/compiler/CodeGenHLSL.cpp | 33 - src/3rdparty/angle/src/compiler/Common.h | 77 - src/3rdparty/angle/src/compiler/Compiler.cpp | 433 --- src/3rdparty/angle/src/compiler/ConstantUnion.h | 257 -- .../angle/src/compiler/DetectCallDepth.cpp | 185 - src/3rdparty/angle/src/compiler/DetectCallDepth.h | 80 - .../angle/src/compiler/DetectDiscontinuity.cpp | 139 - .../angle/src/compiler/DetectDiscontinuity.h | 52 - .../angle/src/compiler/DetectRecursion.cpp | 125 - src/3rdparty/angle/src/compiler/DetectRecursion.h | 60 - src/3rdparty/angle/src/compiler/Diagnostics.cpp | 63 - src/3rdparty/angle/src/compiler/Diagnostics.h | 44 - .../angle/src/compiler/DirectiveHandler.cpp | 161 - src/3rdparty/angle/src/compiler/DirectiveHandler.h | 46 - .../angle/src/compiler/ExtensionBehavior.h | 37 - src/3rdparty/angle/src/compiler/ForLoopUnroll.cpp | 215 -- src/3rdparty/angle/src/compiler/ForLoopUnroll.h | 48 - src/3rdparty/angle/src/compiler/HashNames.h | 19 - src/3rdparty/angle/src/compiler/InfoSink.cpp | 54 - src/3rdparty/angle/src/compiler/InfoSink.h | 115 - src/3rdparty/angle/src/compiler/Initialize.cpp | 564 --- src/3rdparty/angle/src/compiler/Initialize.h | 23 - src/3rdparty/angle/src/compiler/InitializeDll.cpp | 32 - src/3rdparty/angle/src/compiler/InitializeDll.h | 13 - .../angle/src/compiler/InitializeGLPosition.cpp | 61 - .../angle/src/compiler/InitializeGLPosition.h | 33 - .../angle/src/compiler/InitializeGlobals.h | 13 - .../angle/src/compiler/InitializeParseContext.cpp | 40 - .../angle/src/compiler/InitializeParseContext.h | 17 - src/3rdparty/angle/src/compiler/IntermTraverse.cpp | 293 -- src/3rdparty/angle/src/compiler/Intermediate.cpp | 1442 -------- src/3rdparty/angle/src/compiler/MMap.h | 56 - .../angle/src/compiler/MapLongVariableNames.cpp | 122 - .../angle/src/compiler/MapLongVariableNames.h | 59 - src/3rdparty/angle/src/compiler/OutputESSL.cpp | 26 - src/3rdparty/angle/src/compiler/OutputESSL.h | 25 - src/3rdparty/angle/src/compiler/OutputGLSL.cpp | 35 - src/3rdparty/angle/src/compiler/OutputGLSL.h | 26 - src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp | 817 ----- src/3rdparty/angle/src/compiler/OutputGLSLBase.h | 79 - src/3rdparty/angle/src/compiler/OutputHLSL.cpp | 3094 ----------------- src/3rdparty/angle/src/compiler/OutputHLSL.h | 166 - src/3rdparty/angle/src/compiler/ParseHelper.cpp | 1602 --------- src/3rdparty/angle/src/compiler/ParseHelper.h | 134 - src/3rdparty/angle/src/compiler/PoolAlloc.cpp | 294 -- src/3rdparty/angle/src/compiler/PoolAlloc.h | 300 -- src/3rdparty/angle/src/compiler/Pragma.h | 19 - src/3rdparty/angle/src/compiler/QualifierAlive.cpp | 58 - src/3rdparty/angle/src/compiler/QualifierAlive.h | 7 - src/3rdparty/angle/src/compiler/RemoveTree.cpp | 77 - src/3rdparty/angle/src/compiler/RemoveTree.h | 7 - src/3rdparty/angle/src/compiler/RenameFunction.h | 36 - src/3rdparty/angle/src/compiler/SearchSymbol.cpp | 38 - src/3rdparty/angle/src/compiler/SearchSymbol.h | 33 - src/3rdparty/angle/src/compiler/ShHandle.h | 169 - src/3rdparty/angle/src/compiler/ShaderLang.cpp | 387 --- src/3rdparty/angle/src/compiler/SymbolTable.cpp | 216 -- src/3rdparty/angle/src/compiler/SymbolTable.h | 382 -- src/3rdparty/angle/src/compiler/TranslatorESSL.cpp | 43 - src/3rdparty/angle/src/compiler/TranslatorESSL.h | 23 - src/3rdparty/angle/src/compiler/TranslatorGLSL.cpp | 44 - src/3rdparty/angle/src/compiler/TranslatorGLSL.h | 20 - src/3rdparty/angle/src/compiler/TranslatorHLSL.cpp | 24 - src/3rdparty/angle/src/compiler/TranslatorHLSL.h | 27 - src/3rdparty/angle/src/compiler/Types.h | 307 -- .../angle/src/compiler/UnfoldShortCircuit.cpp | 176 - .../angle/src/compiler/UnfoldShortCircuit.h | 39 - src/3rdparty/angle/src/compiler/Uniform.cpp | 21 - src/3rdparty/angle/src/compiler/Uniform.h | 35 - .../angle/src/compiler/ValidateLimitations.cpp | 512 --- .../angle/src/compiler/ValidateLimitations.h | 59 - src/3rdparty/angle/src/compiler/VariableInfo.cpp | 308 -- src/3rdparty/angle/src/compiler/VariableInfo.h | 51 - src/3rdparty/angle/src/compiler/VariablePacker.cpp | 297 -- src/3rdparty/angle/src/compiler/VariablePacker.h | 41 - src/3rdparty/angle/src/compiler/VersionGLSL.cpp | 140 - src/3rdparty/angle/src/compiler/VersionGLSL.h | 56 - src/3rdparty/angle/src/compiler/debug.cpp | 37 - src/3rdparty/angle/src/compiler/debug.h | 53 - .../src/compiler/depgraph/DependencyGraph.cpp | 97 - .../angle/src/compiler/depgraph/DependencyGraph.h | 212 -- .../compiler/depgraph/DependencyGraphBuilder.cpp | 227 -- .../src/compiler/depgraph/DependencyGraphBuilder.h | 181 - .../compiler/depgraph/DependencyGraphOutput.cpp | 65 - .../src/compiler/depgraph/DependencyGraphOutput.h | 30 - .../compiler/depgraph/DependencyGraphTraverse.cpp | 69 - src/3rdparty/angle/src/compiler/glslang.h | 16 - src/3rdparty/angle/src/compiler/glslang.l | 355 -- src/3rdparty/angle/src/compiler/glslang.y | 2002 ----------- src/3rdparty/angle/src/compiler/intermOut.cpp | 424 --- src/3rdparty/angle/src/compiler/intermediate.h | 579 --- .../angle/src/compiler/localintermediate.h | 57 - src/3rdparty/angle/src/compiler/osinclude.h | 58 - src/3rdparty/angle/src/compiler/ossource_posix.cpp | 72 - src/3rdparty/angle/src/compiler/ossource_win.cpp | 65 - src/3rdparty/angle/src/compiler/ossource_winrt.cpp | 75 - src/3rdparty/angle/src/compiler/parseConst.cpp | 245 -- .../src/compiler/preprocessor/DiagnosticsBase.cpp | 84 +- .../src/compiler/preprocessor/DiagnosticsBase.h | 86 +- .../src/compiler/preprocessor/DirectiveParser.cpp | 78 +- .../src/compiler/preprocessor/ExpressionParser.y | 18 +- .../src/compiler/preprocessor/MacroExpander.cpp | 6 +- .../src/compiler/preprocessor/Preprocessor.cpp | 4 +- .../angle/src/compiler/preprocessor/Tokenizer.l | 4 +- .../timing/RestrictFragmentShaderTiming.cpp | 127 - .../compiler/timing/RestrictFragmentShaderTiming.h | 40 - .../compiler/timing/RestrictVertexShaderTiming.cpp | 17 - .../compiler/timing/RestrictVertexShaderTiming.h | 33 - .../angle/src/compiler/translator/BaseTypes.h | 149 + .../translator/BuiltInFunctionEmulator.cpp | 406 +++ .../compiler/translator/BuiltInFunctionEmulator.h | 93 + .../angle/src/compiler/translator/CodeGen.cpp | 38 + .../angle/src/compiler/translator/Common.h | 92 + .../angle/src/compiler/translator/Compiler.cpp | 527 +++ .../angle/src/compiler/translator/ConstantUnion.h | 257 ++ .../src/compiler/translator/DetectCallDepth.cpp | 185 + .../src/compiler/translator/DetectCallDepth.h | 80 + .../compiler/translator/DetectDiscontinuity.cpp | 139 + .../src/compiler/translator/DetectDiscontinuity.h | 52 + .../angle/src/compiler/translator/Diagnostics.cpp | 63 + .../angle/src/compiler/translator/Diagnostics.h | 44 + .../src/compiler/translator/DirectiveHandler.cpp | 161 + .../src/compiler/translator/DirectiveHandler.h | 46 + .../src/compiler/translator/ExtensionBehavior.h | 37 + .../src/compiler/translator/ForLoopUnroll.cpp | 215 ++ .../angle/src/compiler/translator/ForLoopUnroll.h | 52 + .../angle/src/compiler/translator/HashNames.h | 19 + .../angle/src/compiler/translator/InfoSink.cpp | 54 + .../angle/src/compiler/translator/InfoSink.h | 116 + .../angle/src/compiler/translator/Initialize.cpp | 564 +++ .../angle/src/compiler/translator/Initialize.h | 23 + .../src/compiler/translator/InitializeDll.cpp | 32 + .../angle/src/compiler/translator/InitializeDll.h | 13 + .../src/compiler/translator/InitializeGlobals.h | 13 + .../compiler/translator/InitializeParseContext.cpp | 40 + .../compiler/translator/InitializeParseContext.h | 17 + .../compiler/translator/InitializeVariables.cpp | 116 + .../src/compiler/translator/InitializeVariables.h | 50 + .../src/compiler/translator/IntermTraverse.cpp | 259 ++ .../angle/src/compiler/translator/Intermediate.cpp | 1500 ++++++++ src/3rdparty/angle/src/compiler/translator/MMap.h | 56 + .../compiler/translator/MapLongVariableNames.cpp | 115 + .../src/compiler/translator/MapLongVariableNames.h | 58 + .../angle/src/compiler/translator/NodeSearch.h | 80 + .../angle/src/compiler/translator/OutputESSL.cpp | 26 + .../angle/src/compiler/translator/OutputESSL.h | 25 + .../angle/src/compiler/translator/OutputGLSL.cpp | 35 + .../angle/src/compiler/translator/OutputGLSL.h | 26 + .../src/compiler/translator/OutputGLSLBase.cpp | 817 +++++ .../angle/src/compiler/translator/OutputGLSLBase.h | 79 + .../angle/src/compiler/translator/OutputHLSL.cpp | 3138 +++++++++++++++++ .../angle/src/compiler/translator/OutputHLSL.h | 167 + .../angle/src/compiler/translator/ParseContext.cpp | 1602 +++++++++ .../angle/src/compiler/translator/ParseContext.h | 134 + .../angle/src/compiler/translator/PoolAlloc.cpp | 294 ++ .../angle/src/compiler/translator/PoolAlloc.h | 300 ++ .../angle/src/compiler/translator/Pragma.h | 19 + .../src/compiler/translator/QualifierAlive.cpp | 58 + .../angle/src/compiler/translator/QualifierAlive.h | 7 + .../angle/src/compiler/translator/RemoveTree.cpp | 77 + .../angle/src/compiler/translator/RemoveTree.h | 7 + .../angle/src/compiler/translator/RenameFunction.h | 36 + .../src/compiler/translator/RewriteElseBlocks.cpp | 98 + .../src/compiler/translator/RewriteElseBlocks.h | 39 + .../angle/src/compiler/translator/SearchSymbol.cpp | 38 + .../angle/src/compiler/translator/SearchSymbol.h | 33 + .../angle/src/compiler/translator/ShHandle.h | 179 + .../angle/src/compiler/translator/ShaderLang.cpp | 390 +++ .../angle/src/compiler/translator/SymbolTable.cpp | 216 ++ .../angle/src/compiler/translator/SymbolTable.h | 382 ++ .../src/compiler/translator/TranslatorESSL.cpp | 43 + .../angle/src/compiler/translator/TranslatorESSL.h | 23 + .../src/compiler/translator/TranslatorGLSL.cpp | 44 + .../angle/src/compiler/translator/TranslatorGLSL.h | 20 + .../src/compiler/translator/TranslatorHLSL.cpp | 24 + .../angle/src/compiler/translator/TranslatorHLSL.h | 27 + src/3rdparty/angle/src/compiler/translator/Types.h | 307 ++ .../src/compiler/translator/UnfoldShortCircuit.cpp | 184 + .../src/compiler/translator/UnfoldShortCircuit.h | 39 + .../compiler/translator/UnfoldShortCircuitAST.cpp | 81 + .../compiler/translator/UnfoldShortCircuitAST.h | 51 + .../angle/src/compiler/translator/Uniform.cpp | 21 + .../angle/src/compiler/translator/Uniform.h | 35 + .../compiler/translator/ValidateLimitations.cpp | 512 +++ .../src/compiler/translator/ValidateLimitations.h | 59 + .../angle/src/compiler/translator/VariableInfo.cpp | 312 ++ .../angle/src/compiler/translator/VariableInfo.h | 52 + .../src/compiler/translator/VariablePacker.cpp | 297 ++ .../angle/src/compiler/translator/VariablePacker.h | 41 + .../angle/src/compiler/translator/VersionGLSL.cpp | 140 + .../angle/src/compiler/translator/VersionGLSL.h | 56 + .../src/compiler/translator/compilerdebug.cpp | 37 + .../angle/src/compiler/translator/compilerdebug.h | 53 + .../translator/depgraph/DependencyGraph.cpp | 97 + .../compiler/translator/depgraph/DependencyGraph.h | 212 ++ .../translator/depgraph/DependencyGraphBuilder.cpp | 227 ++ .../translator/depgraph/DependencyGraphBuilder.h | 181 + .../translator/depgraph/DependencyGraphOutput.cpp | 65 + .../translator/depgraph/DependencyGraphOutput.h | 30 + .../depgraph/DependencyGraphTraverse.cpp | 69 + .../angle/src/compiler/translator/glslang.h | 16 + .../angle/src/compiler/translator/glslang.l | 355 ++ .../angle/src/compiler/translator/glslang.y | 2014 +++++++++++ .../angle/src/compiler/translator/intermOut.cpp | 424 +++ .../angle/src/compiler/translator/intermediate.h | 635 ++++ .../src/compiler/translator/localintermediate.h | 57 + .../angle/src/compiler/translator/osinclude.h | 64 + .../src/compiler/translator/ossource_posix.cpp | 72 + .../angle/src/compiler/translator/ossource_win.cpp | 65 + .../src/compiler/translator/ossource_winrt.cpp | 75 + .../angle/src/compiler/translator/parseConst.cpp | 245 ++ .../timing/RestrictFragmentShaderTiming.cpp | 127 + .../timing/RestrictFragmentShaderTiming.h | 40 + .../timing/RestrictVertexShaderTiming.cpp | 17 + .../translator/timing/RestrictVertexShaderTiming.h | 33 + .../angle/src/compiler/translator/util.cpp | 28 + src/3rdparty/angle/src/compiler/translator/util.h | 20 + src/3rdparty/angle/src/compiler/util.cpp | 28 - src/3rdparty/angle/src/compiler/util.h | 20 - src/3rdparty/angle/src/libEGL/Display.cpp | 11 +- src/3rdparty/angle/src/libEGL/Display.h | 5 +- src/3rdparty/angle/src/libEGL/Surface.cpp | 41 +- src/3rdparty/angle/src/libEGL/Surface.h | 3 +- src/3rdparty/angle/src/libEGL/libEGL.cpp | 12 +- src/3rdparty/angle/src/libEGL/libEGL.rc | 11 +- src/3rdparty/angle/src/libEGL/main.cpp | 135 +- src/3rdparty/angle/src/libGLESv2/Buffer.cpp | 8 +- src/3rdparty/angle/src/libGLESv2/Buffer.h | 4 +- src/3rdparty/angle/src/libGLESv2/Context.cpp | 30 +- src/3rdparty/angle/src/libGLESv2/Context.h | 9 +- src/3rdparty/angle/src/libGLESv2/Framebuffer.h | 2 +- src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp | 37 +- src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp | 15 + src/3rdparty/angle/src/libGLESv2/Renderbuffer.h | 5 + src/3rdparty/angle/src/libGLESv2/Shader.cpp | 2 + src/3rdparty/angle/src/libGLESv2/Shader.h | 3 +- src/3rdparty/angle/src/libGLESv2/Texture.cpp | 8 +- src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp | 10 +- src/3rdparty/angle/src/libGLESv2/libGLESv2.rc | 11 +- src/3rdparty/angle/src/libGLESv2/main.cpp | 112 +- src/3rdparty/angle/src/libGLESv2/main.h | 3 +- src/3rdparty/angle/src/libGLESv2/mathutil.h | 1 - src/3rdparty/angle/src/libGLESv2/precompiled.h | 57 +- src/3rdparty/angle/src/libGLESv2/renderer/Blit.cpp | 595 ---- src/3rdparty/angle/src/libGLESv2/renderer/Blit.h | 94 - .../angle/src/libGLESv2/renderer/BufferStorage.h | 2 +- .../src/libGLESv2/renderer/BufferStorage11.cpp | 361 -- .../angle/src/libGLESv2/renderer/BufferStorage11.h | 56 - .../src/libGLESv2/renderer/BufferStorage9.cpp | 78 - .../angle/src/libGLESv2/renderer/BufferStorage9.h | 42 - .../angle/src/libGLESv2/renderer/Fence11.cpp | 134 - .../angle/src/libGLESv2/renderer/Fence11.h | 39 - .../angle/src/libGLESv2/renderer/Fence9.cpp | 135 - src/3rdparty/angle/src/libGLESv2/renderer/Fence9.h | 39 - .../angle/src/libGLESv2/renderer/Image11.cpp | 460 --- .../angle/src/libGLESv2/renderer/Image11.h | 76 - .../angle/src/libGLESv2/renderer/Image9.cpp | 736 ---- src/3rdparty/angle/src/libGLESv2/renderer/Image9.h | 79 - .../angle/src/libGLESv2/renderer/IndexBuffer11.cpp | 183 - .../angle/src/libGLESv2/renderer/IndexBuffer11.h | 53 - .../angle/src/libGLESv2/renderer/IndexBuffer9.cpp | 207 -- .../angle/src/libGLESv2/renderer/IndexBuffer9.h | 53 - .../src/libGLESv2/renderer/InputLayoutCache.cpp | 213 -- .../src/libGLESv2/renderer/InputLayoutCache.h | 95 - .../angle/src/libGLESv2/renderer/Query11.cpp | 122 - .../angle/src/libGLESv2/renderer/Query11.h | 40 - .../angle/src/libGLESv2/renderer/Query9.cpp | 125 - src/3rdparty/angle/src/libGLESv2/renderer/Query9.h | 40 - .../src/libGLESv2/renderer/RenderStateCache.cpp | 407 --- .../src/libGLESv2/renderer/RenderStateCache.h | 101 - .../src/libGLESv2/renderer/RenderTarget11.cpp | 355 -- .../angle/src/libGLESv2/renderer/RenderTarget11.h | 51 - .../angle/src/libGLESv2/renderer/RenderTarget9.cpp | 113 - .../angle/src/libGLESv2/renderer/RenderTarget9.h | 40 - .../angle/src/libGLESv2/renderer/Renderer.cpp | 83 +- .../angle/src/libGLESv2/renderer/Renderer.h | 34 +- .../angle/src/libGLESv2/renderer/Renderer11.cpp | 3672 -------------------- .../angle/src/libGLESv2/renderer/Renderer11.h | 360 -- .../angle/src/libGLESv2/renderer/Renderer9.cpp | 3260 ----------------- .../angle/src/libGLESv2/renderer/Renderer9.h | 350 -- .../src/libGLESv2/renderer/ShaderExecutable11.cpp | 109 - .../src/libGLESv2/renderer/ShaderExecutable11.h | 47 - .../src/libGLESv2/renderer/ShaderExecutable9.cpp | 60 - .../src/libGLESv2/renderer/ShaderExecutable9.h | 39 - .../angle/src/libGLESv2/renderer/SwapChain.h | 7 +- .../angle/src/libGLESv2/renderer/SwapChain11.cpp | 797 ----- .../angle/src/libGLESv2/renderer/SwapChain11.h | 78 - .../angle/src/libGLESv2/renderer/SwapChain9.cpp | 449 --- .../angle/src/libGLESv2/renderer/SwapChain9.h | 55 - .../src/libGLESv2/renderer/TextureStorage11.cpp | 667 ---- .../src/libGLESv2/renderer/TextureStorage11.h | 120 - .../src/libGLESv2/renderer/TextureStorage9.cpp | 328 -- .../angle/src/libGLESv2/renderer/TextureStorage9.h | 109 - .../src/libGLESv2/renderer/VertexBuffer11.cpp | 440 --- .../angle/src/libGLESv2/renderer/VertexBuffer11.h | 74 - .../angle/src/libGLESv2/renderer/VertexBuffer9.cpp | 530 --- .../angle/src/libGLESv2/renderer/VertexBuffer9.h | 91 - .../src/libGLESv2/renderer/VertexDataManager.cpp | 4 + .../libGLESv2/renderer/VertexDeclarationCache.cpp | 217 -- .../libGLESv2/renderer/VertexDeclarationCache.h | 58 - .../libGLESv2/renderer/d3d11/BufferStorage11.cpp | 366 ++ .../src/libGLESv2/renderer/d3d11/BufferStorage11.h | 92 + .../angle/src/libGLESv2/renderer/d3d11/Fence11.cpp | 134 + .../angle/src/libGLESv2/renderer/d3d11/Fence11.h | 39 + .../angle/src/libGLESv2/renderer/d3d11/Image11.cpp | 498 +++ .../angle/src/libGLESv2/renderer/d3d11/Image11.h | 76 + .../src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp | 183 + .../src/libGLESv2/renderer/d3d11/IndexBuffer11.h | 53 + .../libGLESv2/renderer/d3d11/InputLayoutCache.cpp | 213 ++ .../libGLESv2/renderer/d3d11/InputLayoutCache.h | 95 + .../angle/src/libGLESv2/renderer/d3d11/Query11.cpp | 122 + .../angle/src/libGLESv2/renderer/d3d11/Query11.h | 40 + .../libGLESv2/renderer/d3d11/RenderStateCache.cpp | 439 +++ .../libGLESv2/renderer/d3d11/RenderStateCache.h | 111 + .../libGLESv2/renderer/d3d11/RenderTarget11.cpp | 355 ++ .../src/libGLESv2/renderer/d3d11/RenderTarget11.h | 51 + .../src/libGLESv2/renderer/d3d11/Renderer11.cpp | 3670 +++++++++++++++++++ .../src/libGLESv2/renderer/d3d11/Renderer11.h | 358 ++ .../renderer/d3d11/ShaderExecutable11.cpp | 109 + .../libGLESv2/renderer/d3d11/ShaderExecutable11.h | 47 + .../src/libGLESv2/renderer/d3d11/SwapChain11.cpp | 700 ++++ .../src/libGLESv2/renderer/d3d11/SwapChain11.h | 78 + .../libGLESv2/renderer/d3d11/TextureStorage11.cpp | 667 ++++ .../libGLESv2/renderer/d3d11/TextureStorage11.h | 120 + .../libGLESv2/renderer/d3d11/VertexBuffer11.cpp | 440 +++ .../src/libGLESv2/renderer/d3d11/VertexBuffer11.h | 74 + .../libGLESv2/renderer/d3d11/renderer11_utils.cpp | 688 ++++ .../libGLESv2/renderer/d3d11/renderer11_utils.h | 95 + .../libGLESv2/renderer/d3d11/shaders/Clear11.hlsl | 42 + .../renderer/d3d11/shaders/Passthrough11.hlsl | 29 + .../angle/src/libGLESv2/renderer/d3d9/Blit.cpp | 595 ++++ .../angle/src/libGLESv2/renderer/d3d9/Blit.h | 94 + .../src/libGLESv2/renderer/d3d9/BufferStorage9.cpp | 78 + .../src/libGLESv2/renderer/d3d9/BufferStorage9.h | 42 + .../angle/src/libGLESv2/renderer/d3d9/Fence9.cpp | 135 + .../angle/src/libGLESv2/renderer/d3d9/Fence9.h | 39 + .../angle/src/libGLESv2/renderer/d3d9/Image9.cpp | 736 ++++ .../angle/src/libGLESv2/renderer/d3d9/Image9.h | 79 + .../src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp | 207 ++ .../src/libGLESv2/renderer/d3d9/IndexBuffer9.h | 53 + .../angle/src/libGLESv2/renderer/d3d9/Query9.cpp | 125 + .../angle/src/libGLESv2/renderer/d3d9/Query9.h | 40 + .../src/libGLESv2/renderer/d3d9/RenderTarget9.cpp | 113 + .../src/libGLESv2/renderer/d3d9/RenderTarget9.h | 40 + .../src/libGLESv2/renderer/d3d9/Renderer9.cpp | 3287 ++++++++++++++++++ .../angle/src/libGLESv2/renderer/d3d9/Renderer9.h | 356 ++ .../libGLESv2/renderer/d3d9/ShaderExecutable9.cpp | 60 + .../libGLESv2/renderer/d3d9/ShaderExecutable9.h | 39 + .../src/libGLESv2/renderer/d3d9/SwapChain9.cpp | 445 +++ .../angle/src/libGLESv2/renderer/d3d9/SwapChain9.h | 55 + .../libGLESv2/renderer/d3d9/TextureStorage9.cpp | 328 ++ .../src/libGLESv2/renderer/d3d9/TextureStorage9.h | 109 + .../src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp | 530 +++ .../src/libGLESv2/renderer/d3d9/VertexBuffer9.h | 91 + .../renderer/d3d9/VertexDeclarationCache.cpp | 217 ++ .../renderer/d3d9/VertexDeclarationCache.h | 58 + .../libGLESv2/renderer/d3d9/renderer9_utils.cpp | 500 +++ .../src/libGLESv2/renderer/d3d9/renderer9_utils.h | 74 + .../src/libGLESv2/renderer/d3d9/shaders/Blit.ps | 39 + .../src/libGLESv2/renderer/d3d9/shaders/Blit.vs | 43 + .../src/libGLESv2/renderer/d3d9/vertexconversion.h | 203 ++ .../src/libGLESv2/renderer/renderer11_utils.cpp | 688 ---- .../src/libGLESv2/renderer/renderer11_utils.h | 95 - .../src/libGLESv2/renderer/renderer9_utils.cpp | 500 --- .../angle/src/libGLESv2/renderer/renderer9_utils.h | 74 - .../angle/src/libGLESv2/renderer/shaders/Blit.ps | 39 - .../angle/src/libGLESv2/renderer/shaders/Blit.vs | 43 - .../src/libGLESv2/renderer/shaders/Clear11.hlsl | 42 - .../libGLESv2/renderer/shaders/Passthrough11.hlsl | 29 - .../src/libGLESv2/renderer/vertexconversion.h | 203 -- src/3rdparty/angle/src/libGLESv2/utilities.cpp | 63 +- .../src/third_party/compiler/ArrayBoundsClamper.h | 4 +- .../src/third_party/trace_event/trace_event.h | 4 +- 385 files changed, 41061 insertions(+), 40379 deletions(-) create mode 100644 src/3rdparty/angle/src/commit.h delete mode 100644 src/3rdparty/angle/src/common/system.h delete mode 100644 src/3rdparty/angle/src/compiler/BaseTypes.h delete mode 100644 src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.cpp delete mode 100644 src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.h delete mode 100644 src/3rdparty/angle/src/compiler/CodeGenGLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/CodeGenHLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/Common.h delete mode 100644 src/3rdparty/angle/src/compiler/Compiler.cpp delete mode 100644 src/3rdparty/angle/src/compiler/ConstantUnion.h delete mode 100644 src/3rdparty/angle/src/compiler/DetectCallDepth.cpp delete mode 100644 src/3rdparty/angle/src/compiler/DetectCallDepth.h delete mode 100644 src/3rdparty/angle/src/compiler/DetectDiscontinuity.cpp delete mode 100644 src/3rdparty/angle/src/compiler/DetectDiscontinuity.h delete mode 100644 src/3rdparty/angle/src/compiler/DetectRecursion.cpp delete mode 100644 src/3rdparty/angle/src/compiler/DetectRecursion.h delete mode 100644 src/3rdparty/angle/src/compiler/Diagnostics.cpp delete mode 100644 src/3rdparty/angle/src/compiler/Diagnostics.h delete mode 100644 src/3rdparty/angle/src/compiler/DirectiveHandler.cpp delete mode 100644 src/3rdparty/angle/src/compiler/DirectiveHandler.h delete mode 100644 src/3rdparty/angle/src/compiler/ExtensionBehavior.h delete mode 100644 src/3rdparty/angle/src/compiler/ForLoopUnroll.cpp delete mode 100644 src/3rdparty/angle/src/compiler/ForLoopUnroll.h delete mode 100644 src/3rdparty/angle/src/compiler/HashNames.h delete mode 100644 src/3rdparty/angle/src/compiler/InfoSink.cpp delete mode 100644 src/3rdparty/angle/src/compiler/InfoSink.h delete mode 100644 src/3rdparty/angle/src/compiler/Initialize.cpp delete mode 100644 src/3rdparty/angle/src/compiler/Initialize.h delete mode 100644 src/3rdparty/angle/src/compiler/InitializeDll.cpp delete mode 100644 src/3rdparty/angle/src/compiler/InitializeDll.h delete mode 100644 src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp delete mode 100644 src/3rdparty/angle/src/compiler/InitializeGLPosition.h delete mode 100644 src/3rdparty/angle/src/compiler/InitializeGlobals.h delete mode 100644 src/3rdparty/angle/src/compiler/InitializeParseContext.cpp delete mode 100644 src/3rdparty/angle/src/compiler/InitializeParseContext.h delete mode 100644 src/3rdparty/angle/src/compiler/IntermTraverse.cpp delete mode 100644 src/3rdparty/angle/src/compiler/Intermediate.cpp delete mode 100644 src/3rdparty/angle/src/compiler/MMap.h delete mode 100644 src/3rdparty/angle/src/compiler/MapLongVariableNames.cpp delete mode 100644 src/3rdparty/angle/src/compiler/MapLongVariableNames.h delete mode 100644 src/3rdparty/angle/src/compiler/OutputESSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/OutputESSL.h delete mode 100644 src/3rdparty/angle/src/compiler/OutputGLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/OutputGLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp delete mode 100644 src/3rdparty/angle/src/compiler/OutputGLSLBase.h delete mode 100644 src/3rdparty/angle/src/compiler/OutputHLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/OutputHLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/ParseHelper.cpp delete mode 100644 src/3rdparty/angle/src/compiler/ParseHelper.h delete mode 100644 src/3rdparty/angle/src/compiler/PoolAlloc.cpp delete mode 100644 src/3rdparty/angle/src/compiler/PoolAlloc.h delete mode 100644 src/3rdparty/angle/src/compiler/Pragma.h delete mode 100644 src/3rdparty/angle/src/compiler/QualifierAlive.cpp delete mode 100644 src/3rdparty/angle/src/compiler/QualifierAlive.h delete mode 100644 src/3rdparty/angle/src/compiler/RemoveTree.cpp delete mode 100644 src/3rdparty/angle/src/compiler/RemoveTree.h delete mode 100644 src/3rdparty/angle/src/compiler/RenameFunction.h delete mode 100644 src/3rdparty/angle/src/compiler/SearchSymbol.cpp delete mode 100644 src/3rdparty/angle/src/compiler/SearchSymbol.h delete mode 100644 src/3rdparty/angle/src/compiler/ShHandle.h delete mode 100644 src/3rdparty/angle/src/compiler/ShaderLang.cpp delete mode 100644 src/3rdparty/angle/src/compiler/SymbolTable.cpp delete mode 100644 src/3rdparty/angle/src/compiler/SymbolTable.h delete mode 100644 src/3rdparty/angle/src/compiler/TranslatorESSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/TranslatorESSL.h delete mode 100644 src/3rdparty/angle/src/compiler/TranslatorGLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/TranslatorGLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/TranslatorHLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/TranslatorHLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/Types.h delete mode 100644 src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp delete mode 100644 src/3rdparty/angle/src/compiler/UnfoldShortCircuit.h delete mode 100644 src/3rdparty/angle/src/compiler/Uniform.cpp delete mode 100644 src/3rdparty/angle/src/compiler/Uniform.h delete mode 100644 src/3rdparty/angle/src/compiler/ValidateLimitations.cpp delete mode 100644 src/3rdparty/angle/src/compiler/ValidateLimitations.h delete mode 100644 src/3rdparty/angle/src/compiler/VariableInfo.cpp delete mode 100644 src/3rdparty/angle/src/compiler/VariableInfo.h delete mode 100644 src/3rdparty/angle/src/compiler/VariablePacker.cpp delete mode 100644 src/3rdparty/angle/src/compiler/VariablePacker.h delete mode 100644 src/3rdparty/angle/src/compiler/VersionGLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/VersionGLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/debug.cpp delete mode 100644 src/3rdparty/angle/src/compiler/debug.h delete mode 100644 src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.cpp delete mode 100644 src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.h delete mode 100644 src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.cpp delete mode 100644 src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.h delete mode 100644 src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.cpp delete mode 100644 src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.h delete mode 100644 src/3rdparty/angle/src/compiler/depgraph/DependencyGraphTraverse.cpp delete mode 100644 src/3rdparty/angle/src/compiler/glslang.h delete mode 100644 src/3rdparty/angle/src/compiler/glslang.l delete mode 100644 src/3rdparty/angle/src/compiler/glslang.y delete mode 100644 src/3rdparty/angle/src/compiler/intermOut.cpp delete mode 100644 src/3rdparty/angle/src/compiler/intermediate.h delete mode 100644 src/3rdparty/angle/src/compiler/localintermediate.h delete mode 100644 src/3rdparty/angle/src/compiler/osinclude.h delete mode 100644 src/3rdparty/angle/src/compiler/ossource_posix.cpp delete mode 100644 src/3rdparty/angle/src/compiler/ossource_win.cpp delete mode 100644 src/3rdparty/angle/src/compiler/ossource_winrt.cpp delete mode 100644 src/3rdparty/angle/src/compiler/parseConst.cpp delete mode 100644 src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.cpp delete mode 100644 src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.h delete mode 100644 src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp delete mode 100644 src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.h create mode 100644 src/3rdparty/angle/src/compiler/translator/BaseTypes.h create mode 100644 src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h create mode 100644 src/3rdparty/angle/src/compiler/translator/CodeGen.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/Common.h create mode 100644 src/3rdparty/angle/src/compiler/translator/Compiler.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/ConstantUnion.h create mode 100644 src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h create mode 100644 src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h create mode 100644 src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/Diagnostics.h create mode 100644 src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h create mode 100644 src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h create mode 100644 src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h create mode 100644 src/3rdparty/angle/src/compiler/translator/HashNames.h create mode 100644 src/3rdparty/angle/src/compiler/translator/InfoSink.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/InfoSink.h create mode 100644 src/3rdparty/angle/src/compiler/translator/Initialize.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/Initialize.h create mode 100644 src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/InitializeDll.h create mode 100644 src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h create mode 100644 src/3rdparty/angle/src/compiler/translator/InitializeParseContext.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h create mode 100644 src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/InitializeVariables.h create mode 100644 src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/Intermediate.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/MMap.h create mode 100644 src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.h create mode 100644 src/3rdparty/angle/src/compiler/translator/NodeSearch.h create mode 100644 src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/OutputESSL.h create mode 100644 src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/OutputGLSL.h create mode 100644 src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h create mode 100644 src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/OutputHLSL.h create mode 100644 src/3rdparty/angle/src/compiler/translator/ParseContext.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/ParseContext.h create mode 100644 src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/PoolAlloc.h create mode 100644 src/3rdparty/angle/src/compiler/translator/Pragma.h create mode 100644 src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/QualifierAlive.h create mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveTree.h create mode 100644 src/3rdparty/angle/src/compiler/translator/RenameFunction.h create mode 100644 src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h create mode 100644 src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/SearchSymbol.h create mode 100644 src/3rdparty/angle/src/compiler/translator/ShHandle.h create mode 100644 src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/SymbolTable.h create mode 100644 src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h create mode 100644 src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h create mode 100644 src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h create mode 100644 src/3rdparty/angle/src/compiler/translator/Types.h create mode 100644 src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h create mode 100644 src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h create mode 100644 src/3rdparty/angle/src/compiler/translator/Uniform.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/Uniform.h create mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h create mode 100644 src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/VariableInfo.h create mode 100644 src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/VariablePacker.h create mode 100644 src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/VersionGLSL.h create mode 100644 src/3rdparty/angle/src/compiler/translator/compilerdebug.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/compilerdebug.h create mode 100644 src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h create mode 100644 src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h create mode 100644 src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h create mode 100644 src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/glslang.h create mode 100644 src/3rdparty/angle/src/compiler/translator/glslang.l create mode 100644 src/3rdparty/angle/src/compiler/translator/glslang.y create mode 100644 src/3rdparty/angle/src/compiler/translator/intermOut.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/intermediate.h create mode 100644 src/3rdparty/angle/src/compiler/translator/localintermediate.h create mode 100644 src/3rdparty/angle/src/compiler/translator/osinclude.h create mode 100644 src/3rdparty/angle/src/compiler/translator/ossource_posix.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/ossource_win.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/ossource_winrt.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/parseConst.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h create mode 100644 src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h create mode 100644 src/3rdparty/angle/src/compiler/translator/util.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/util.h delete mode 100644 src/3rdparty/angle/src/compiler/util.cpp delete mode 100644 src/3rdparty/angle/src/compiler/util.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Blit.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Blit.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Fence11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Fence11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Fence9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Fence9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Image11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Image9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Image9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Query11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Query11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Query9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Query9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexDeclarationCache.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.vs create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/vertexconversion.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/renderer9_utils.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/renderer9_utils.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/shaders/Blit.ps delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/shaders/Blit.vs delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/shaders/Passthrough11.hlsl delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h (limited to 'src/3rdparty/angle/src') diff --git a/src/3rdparty/angle/src/commit.h b/src/3rdparty/angle/src/commit.h new file mode 100644 index 0000000000..f4a36a3cfe --- /dev/null +++ b/src/3rdparty/angle/src/commit.h @@ -0,0 +1,2 @@ +#define ANGLE_COMMIT_HASH "5bb7ec572d0a" +#define ANGLE_COMMIT_HASH_SIZE 12 diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h index 9761567fb2..7723f0fb72 100644 --- a/src/3rdparty/angle/src/common/angleutils.h +++ b/src/3rdparty/angle/src/common/angleutils.h @@ -42,6 +42,20 @@ void SafeRelease(T& resource) } } +template +void SafeDelete(T*& resource) +{ + delete resource; + resource = NULL; +} + +template +void SafeDeleteArray(T*& resource) +{ + delete[] resource; + resource = NULL; +} + #if defined(_MSC_VER) #define snprintf _snprintf #endif diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp index 9b932567b0..05d3dc62ad 100644 --- a/src/3rdparty/angle/src/common/debug.cpp +++ b/src/3rdparty/angle/src/common/debug.cpp @@ -7,21 +7,23 @@ // debug.cpp: Debugging utilities. #include "common/debug.h" -#include "common/system.h" -#ifndef ANGLE_ENABLE_D3D11 +#include + +#if defined(ANGLE_ENABLE_PERF) #include -#else -typedef DWORD D3DCOLOR; #endif namespace gl { - +#if defined(ANGLE_ENABLE_PERF) typedef void (WINAPI *PerfOutputFunction)(D3DCOLOR, LPCWSTR); +#else +typedef void (*PerfOutputFunction)(unsigned int, const wchar_t*); +#endif static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const char *format, va_list vararg) { -#if !defined(ANGLE_DISABLE_PERF) +#if defined(ANGLE_ENABLE_PERF) if (perfActive()) { char message[32768]; @@ -41,15 +43,15 @@ static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const c perfFunc(0, wideMessage); } -#endif +#endif // ANGLE_ENABLE_PERF -#if !defined(ANGLE_DISABLE_TRACE) +#if defined(ANGLE_ENABLE_TRACE) #if defined(NDEBUG) if (traceFileDebugOnly) { return; } -#endif +#endif // NDEBUG FILE* file = fopen(TRACE_OUTPUT_FILE, "a"); if (file) @@ -57,50 +59,50 @@ static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const c vfprintf(file, format, vararg); fclose(file); } -#endif +#endif // ANGLE_ENABLE_TRACE } void trace(bool traceFileDebugOnly, const char *format, ...) { va_list vararg; va_start(vararg, format); -#if defined(ANGLE_DISABLE_PERF) - output(traceFileDebugOnly, NULL, format, vararg); -#else +#if defined(ANGLE_ENABLE_PERF) output(traceFileDebugOnly, D3DPERF_SetMarker, format, vararg); +#else + output(traceFileDebugOnly, NULL, format, vararg); #endif va_end(vararg); } bool perfActive() { -#if defined(ANGLE_DISABLE_PERF) - return false; -#else +#if defined(ANGLE_ENABLE_PERF) static bool active = D3DPERF_GetStatus() != 0; return active; +#else + return false; #endif } ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...) { -#if !defined(ANGLE_DISABLE_PERF) -#if defined(ANGLE_DISABLE_TRACE) +#if defined(ANGLE_ENABLE_PERF) +#if !defined(ANGLE_ENABLE_TRACE) if (!perfActive()) { return; } -#endif +#endif // !ANGLE_ENABLE_TRACE va_list vararg; va_start(vararg, format); output(true, reinterpret_cast(D3DPERF_BeginEvent), format, vararg); va_end(vararg); -#endif +#endif // ANGLE_ENABLE_PERF } ScopedPerfEventHelper::~ScopedPerfEventHelper() { -#if !defined(ANGLE_DISABLE_PERF) +#if defined(ANGLE_ENABLE_PERF) if (perfActive()) { D3DPERF_EndEvent(); diff --git a/src/3rdparty/angle/src/common/debug.h b/src/3rdparty/angle/src/common/debug.h index 23ee26d23b..793843895c 100644 --- a/src/3rdparty/angle/src/common/debug.h +++ b/src/3rdparty/angle/src/common/debug.h @@ -39,33 +39,35 @@ namespace gl } // A macro to output a trace of a function call and its arguments to the debugging log -#if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF) -#define TRACE(message, ...) (void(0)) -#else +#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) #define TRACE(message, ...) gl::trace(true, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else +#define TRACE(message, ...) (void(0)) #endif // A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing. -#if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF) -#define FIXME(message, ...) (void(0)) -#else +#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) #define FIXME(message, ...) gl::trace(false, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else +#define FIXME(message, ...) (void(0)) #endif // A macro to output a function call and its arguments to the debugging log, in case of error. -#if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF) -#define ERR(message, ...) (void(0)) -#else +#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) #define ERR(message, ...) gl::trace(false, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else +#define ERR(message, ...) (void(0)) #endif // A macro to log a performance event around a scope. -#if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF) -#define EVENT(message, ...) (void(0)) -#elif defined(_MSC_VER) +#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) +#if defined(_MSC_VER) #define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__(__FUNCTION__ message "\n", __VA_ARGS__); #else #define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper(message "\n", ##__VA_ARGS__); +#endif // _MSC_VER +#else +#define EVENT(message, ...) (void(0)) #endif // A macro asserting a condition and outputting failures to the debug log @@ -99,8 +101,10 @@ namespace gl #define UNREACHABLE() ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__) #endif -// A macro that determines whether an object has a given runtime type. -#if !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) +// A macro that determines whether an object has a given runtime type. MSVC uses _CPPRTTI. +// GCC uses __GXX_RTTI, but the macro was introduced in version 4.3, so we assume that all older +// versions support RTTI. +#if !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) && (!defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || defined(__GXX_RTTI)) #define HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast(obj) != NULL) #else #define HAS_DYNAMIC_TYPE(type, obj) true diff --git a/src/3rdparty/angle/src/common/event_tracer.cpp b/src/3rdparty/angle/src/common/event_tracer.cpp index 96cbb01061..142373d13f 100644 --- a/src/3rdparty/angle/src/common/event_tracer.cpp +++ b/src/3rdparty/angle/src/common/event_tracer.cpp @@ -14,7 +14,7 @@ AddTraceEventFunc g_addTraceEvent; extern "C" { -void __stdcall SetTraceFunctionPointers(GetCategoryEnabledFlagFunc getCategoryEnabledFlag, +void TRACE_ENTRY SetTraceFunctionPointers(GetCategoryEnabledFlagFunc getCategoryEnabledFlag, AddTraceEventFunc addTraceEvent) { gl::g_getCategoryEnabledFlag = getCategoryEnabledFlag; diff --git a/src/3rdparty/angle/src/common/event_tracer.h b/src/3rdparty/angle/src/common/event_tracer.h index ae397e7db9..14b7b298fd 100644 --- a/src/3rdparty/angle/src/common/event_tracer.h +++ b/src/3rdparty/angle/src/common/event_tracer.h @@ -5,6 +5,14 @@ #ifndef COMMON_EVENT_TRACER_H_ #define COMMON_EVENT_TRACER_H_ +#if !defined(TRACE_ENTRY) +#if defined(_WIN32) +#define TRACE_ENTRY __stdcall +#else +#define TRACE_ENTRY +#endif // // _WIN32 +#endif //TRACE_ENTRY + extern "C" { typedef const unsigned char* (*GetCategoryEnabledFlagFunc)(const char* name); @@ -14,8 +22,8 @@ typedef void (*AddTraceEventFunc)(char phase, const unsigned char* categoryGroup unsigned char flags); // extern "C" so that it has a reasonable name for GetProcAddress. -void __stdcall SetTraceFunctionPointers(GetCategoryEnabledFlagFunc get_category_enabled_flag, - AddTraceEventFunc add_trace_event_func); +void TRACE_ENTRY SetTraceFunctionPointers(GetCategoryEnabledFlagFunc get_category_enabled_flag, + AddTraceEventFunc add_trace_event_func); } diff --git a/src/3rdparty/angle/src/common/system.h b/src/3rdparty/angle/src/common/system.h deleted file mode 100644 index 5eb140bccd..0000000000 --- a/src/3rdparty/angle/src/common/system.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// system.h: Includes Windows system headers and undefines macros that conflict. - -#ifndef COMMON_SYSTEM_H -#define COMMON_SYSTEM_H - -#if !defined(WIN32_LEAN_AND_MEAN) -#define WIN32_LEAN_AND_MEAN -#endif - -#include - -#if defined(min) -#undef min -#endif - -#if defined(max) -#undef max -#endif - -#endif // COMMON_SYSTEM_H diff --git a/src/3rdparty/angle/src/common/version.h b/src/3rdparty/angle/src/common/version.h index 7a4942ad88..f6ae19f541 100644 --- a/src/3rdparty/angle/src/common/version.h +++ b/src/3rdparty/angle/src/common/version.h @@ -1,12 +1,12 @@ -#define MAJOR_VERSION 1 -#define MINOR_VERSION 2 -#define BUILD_VERSION 0 -#define BUILD_REVISION 2446 +#include "commit.h" -#define STRINGIFY(x) #x -#define MACRO_STRINGIFY(x) STRINGIFY(x) +#define ANGLE_MAJOR_VERSION 1 +#define ANGLE_MINOR_VERSION 3 -#define REVISION_STRING MACRO_STRINGIFY(BUILD_REVISION) -#define VERSION_STRING MACRO_STRINGIFY(MAJOR_VERSION) "." MACRO_STRINGIFY(MINOR_VERSION) "." MACRO_STRINGIFY(BUILD_VERSION) "." MACRO_STRINGIFY(BUILD_REVISION) +#define ANGLE_STRINGIFY(x) #x +#define ANGLE_MACRO_STRINGIFY(x) ANGLE_STRINGIFY(x) -#define VERSION_DWORD ((MAJOR_VERSION << 24) | (MINOR_VERSION << 16) | BUILD_REVISION) +#define ANGLE_VERSION_STRING \ + ANGLE_MACRO_STRINGIFY(ANGLE_MAJOR_VERSION) "." \ + ANGLE_MACRO_STRINGIFY(ANGLE_MINOR_VERSION) "." \ + ANGLE_COMMIT_HASH diff --git a/src/3rdparty/angle/src/compiler/BaseTypes.h b/src/3rdparty/angle/src/compiler/BaseTypes.h deleted file mode 100644 index 1631f4f779..0000000000 --- a/src/3rdparty/angle/src/compiler/BaseTypes.h +++ /dev/null @@ -1,148 +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. -// - -#ifndef _BASICTYPES_INCLUDED_ -#define _BASICTYPES_INCLUDED_ - -// -// Precision qualifiers -// -enum TPrecision -{ - // These need to be kept sorted - EbpUndefined, - EbpLow, - EbpMedium, - EbpHigh -}; - -inline const char* getPrecisionString(TPrecision p) -{ - switch(p) - { - case EbpHigh: return "highp"; break; - case EbpMedium: return "mediump"; break; - case EbpLow: return "lowp"; break; - default: return "mediump"; break; // Safest fallback - } -} - -// -// Basic type. Arrays, vectors, etc., are orthogonal to this. -// -enum TBasicType -{ - EbtVoid, - EbtFloat, - EbtInt, - EbtBool, - EbtGuardSamplerBegin, // non type: see implementation of IsSampler() - EbtSampler2D, - EbtSamplerCube, - EbtSamplerExternalOES, // Only valid if OES_EGL_image_external exists. - EbtSampler2DRect, // Only valid if GL_ARB_texture_rectangle exists. - EbtGuardSamplerEnd, // non type: see implementation of IsSampler() - EbtStruct, - EbtAddress, // should be deprecated?? - EbtInvariant // used as a type when qualifying a previously declared variable as being invariant -}; - -inline const char* getBasicString(TBasicType t) -{ - switch (t) - { - case EbtVoid: return "void"; break; - case EbtFloat: return "float"; break; - case EbtInt: return "int"; break; - case EbtBool: return "bool"; break; - case EbtSampler2D: return "sampler2D"; break; - case EbtSamplerCube: return "samplerCube"; break; - case EbtSamplerExternalOES: return "samplerExternalOES"; break; - case EbtSampler2DRect: return "sampler2DRect"; break; - case EbtStruct: return "structure"; break; - default: return "unknown type"; - } -} - -inline bool IsSampler(TBasicType type) -{ - return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd; -} - -// -// Qualifiers and built-ins. These are mainly used to see what can be read -// or written, and by the machine dependent translator to know which registers -// to allocate variables in. Since built-ins tend to go to different registers -// than varying or uniform, it makes sense they are peers, not sub-classes. -// -enum TQualifier -{ - EvqTemporary, // For temporaries (within a function), read/write - EvqGlobal, // For globals read/write - EvqConst, // User defined constants and non-output parameters in functions - EvqAttribute, // Readonly - EvqVaryingIn, // readonly, fragment shaders only - EvqVaryingOut, // vertex shaders only read/write - EvqInvariantVaryingIn, // readonly, fragment shaders only - EvqInvariantVaryingOut, // vertex shaders only read/write - EvqUniform, // Readonly, vertex and fragment - - // parameters - EvqIn, - EvqOut, - EvqInOut, - EvqConstReadOnly, - - // built-ins written by vertex shader - EvqPosition, - EvqPointSize, - - // built-ins read by fragment shader - EvqFragCoord, - EvqFrontFacing, - EvqPointCoord, - - // built-ins written by fragment shader - EvqFragColor, - EvqFragData, - EvqFragDepth, - - // end of list - EvqLast -}; - -// -// This is just for debug print out, carried along with the definitions above. -// -inline const char* getQualifierString(TQualifier q) -{ - switch(q) - { - case EvqTemporary: return "Temporary"; break; - case EvqGlobal: return "Global"; break; - case EvqConst: return "const"; break; - case EvqConstReadOnly: return "const"; break; - case EvqAttribute: return "attribute"; break; - case EvqVaryingIn: return "varying"; break; - case EvqVaryingOut: return "varying"; break; - case EvqInvariantVaryingIn: return "invariant varying"; break; - case EvqInvariantVaryingOut:return "invariant varying"; break; - case EvqUniform: return "uniform"; break; - case EvqIn: return "in"; break; - case EvqOut: return "out"; break; - case EvqInOut: return "inout"; break; - case EvqPosition: return "Position"; break; - case EvqPointSize: return "PointSize"; break; - case EvqFragCoord: return "FragCoord"; break; - case EvqFrontFacing: return "FrontFacing"; break; - case EvqFragColor: return "FragColor"; break; - case EvqFragData: return "FragData"; break; - case EvqFragDepth: return "FragDepth"; break; - default: return "unknown qualifier"; - } -} - -#endif // _BASICTYPES_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.cpp b/src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.cpp deleted file mode 100644 index 1c4b25f13f..0000000000 --- a/src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.cpp +++ /dev/null @@ -1,406 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/BuiltInFunctionEmulator.h" - -#include "compiler/SymbolTable.h" - -namespace { - -// we use macros here instead of function definitions to work around more GLSL -// compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are -// problematic because if the argument has side-effects they will be repeatedly -// evaluated. This is unlikely to show up in real shaders, but is something to -// consider. -const char* kFunctionEmulationVertexSource[] = { - "#error no emulation for cos(float)", - "#error no emulation for cos(vec2)", - "#error no emulation for cos(vec3)", - "#error no emulation for cos(vec4)", - - "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))", - "#error no emulation for distance(vec2, vec2)", - "#error no emulation for distance(vec3, vec3)", - "#error no emulation for distance(vec4, vec4)", - - "#define webgl_dot_emu(x, y) ((x) * (y))", - "#error no emulation for dot(vec2, vec2)", - "#error no emulation for dot(vec3, vec3)", - "#error no emulation for dot(vec4, vec4)", - - "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", - "#error no emulation for length(vec2)", - "#error no emulation for length(vec3)", - "#error no emulation for length(vec4)", - - "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", - "#error no emulation for normalize(vec2)", - "#error no emulation for normalize(vec3)", - "#error no emulation for normalize(vec4)", - - "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))", - "#error no emulation for reflect(vec2, vec2)", - "#error no emulation for reflect(vec3, vec3)", - "#error no emulation for reflect(vec4, vec4)" -}; - -const char* kFunctionEmulationFragmentSource[] = { - "webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }", - "webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }", - "webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }", - "webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }", - - "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))", - "#error no emulation for distance(vec2, vec2)", - "#error no emulation for distance(vec3, vec3)", - "#error no emulation for distance(vec4, vec4)", - - "#define webgl_dot_emu(x, y) ((x) * (y))", - "#error no emulation for dot(vec2, vec2)", - "#error no emulation for dot(vec3, vec3)", - "#error no emulation for dot(vec4, vec4)", - - "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", - "#error no emulation for length(vec2)", - "#error no emulation for length(vec3)", - "#error no emulation for length(vec4)", - - "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", - "#error no emulation for normalize(vec2)", - "#error no emulation for normalize(vec3)", - "#error no emulation for normalize(vec4)", - - "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))", - "#error no emulation for reflect(vec2, vec2)", - "#error no emulation for reflect(vec3, vec3)", - "#error no emulation for reflect(vec4, vec4)" -}; - -const bool kFunctionEmulationVertexMask[] = { -#if defined(__APPLE__) - // Work around ATI driver bugs in Mac. - false, // TFunctionCos1 - false, // TFunctionCos2 - false, // TFunctionCos3 - false, // TFunctionCos4 - true, // TFunctionDistance1_1 - false, // TFunctionDistance2_2 - false, // TFunctionDistance3_3 - false, // TFunctionDistance4_4 - true, // TFunctionDot1_1 - false, // TFunctionDot2_2 - false, // TFunctionDot3_3 - false, // TFunctionDot4_4 - true, // TFunctionLength1 - false, // TFunctionLength2 - false, // TFunctionLength3 - false, // TFunctionLength4 - true, // TFunctionNormalize1 - false, // TFunctionNormalize2 - false, // TFunctionNormalize3 - false, // TFunctionNormalize4 - true, // TFunctionReflect1_1 - false, // TFunctionReflect2_2 - false, // TFunctionReflect3_3 - false, // TFunctionReflect4_4 -#else - // Work around D3D driver bug in Win. - false, // TFunctionCos1 - false, // TFunctionCos2 - false, // TFunctionCos3 - false, // TFunctionCos4 - false, // TFunctionDistance1_1 - false, // TFunctionDistance2_2 - false, // TFunctionDistance3_3 - false, // TFunctionDistance4_4 - false, // TFunctionDot1_1 - false, // TFunctionDot2_2 - false, // TFunctionDot3_3 - false, // TFunctionDot4_4 - false, // TFunctionLength1 - false, // TFunctionLength2 - false, // TFunctionLength3 - false, // TFunctionLength4 - false, // TFunctionNormalize1 - false, // TFunctionNormalize2 - false, // TFunctionNormalize3 - false, // TFunctionNormalize4 - false, // TFunctionReflect1_1 - false, // TFunctionReflect2_2 - false, // TFunctionReflect3_3 - false, // TFunctionReflect4_4 -#endif - false // TFunctionUnknown -}; - -const bool kFunctionEmulationFragmentMask[] = { -#if defined(__APPLE__) - // Work around ATI driver bugs in Mac. - true, // TFunctionCos1 - true, // TFunctionCos2 - true, // TFunctionCos3 - true, // TFunctionCos4 - true, // TFunctionDistance1_1 - false, // TFunctionDistance2_2 - false, // TFunctionDistance3_3 - false, // TFunctionDistance4_4 - true, // TFunctionDot1_1 - false, // TFunctionDot2_2 - false, // TFunctionDot3_3 - false, // TFunctionDot4_4 - true, // TFunctionLength1 - false, // TFunctionLength2 - false, // TFunctionLength3 - false, // TFunctionLength4 - true, // TFunctionNormalize1 - false, // TFunctionNormalize2 - false, // TFunctionNormalize3 - false, // TFunctionNormalize4 - true, // TFunctionReflect1_1 - false, // TFunctionReflect2_2 - false, // TFunctionReflect3_3 - false, // TFunctionReflect4_4 -#else - // Work around D3D driver bug in Win. - false, // TFunctionCos1 - false, // TFunctionCos2 - false, // TFunctionCos3 - false, // TFunctionCos4 - false, // TFunctionDistance1_1 - false, // TFunctionDistance2_2 - false, // TFunctionDistance3_3 - false, // TFunctionDistance4_4 - false, // TFunctionDot1_1 - false, // TFunctionDot2_2 - false, // TFunctionDot3_3 - false, // TFunctionDot4_4 - false, // TFunctionLength1 - false, // TFunctionLength2 - false, // TFunctionLength3 - false, // TFunctionLength4 - false, // TFunctionNormalize1 - false, // TFunctionNormalize2 - false, // TFunctionNormalize3 - false, // TFunctionNormalize4 - false, // TFunctionReflect1_1 - false, // TFunctionReflect2_2 - false, // TFunctionReflect3_3 - false, // TFunctionReflect4_4 -#endif - false // TFunctionUnknown -}; - -class BuiltInFunctionEmulationMarker : public TIntermTraverser { -public: - BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator& emulator) - : mEmulator(emulator) - { - } - - virtual bool visitUnary(Visit visit, TIntermUnary* node) - { - if (visit == PreVisit) { - bool needToEmulate = mEmulator.SetFunctionCalled( - node->getOp(), node->getOperand()->getType()); - if (needToEmulate) - node->setUseEmulatedFunction(); - } - return true; - } - - virtual bool visitAggregate(Visit visit, TIntermAggregate* node) - { - if (visit == PreVisit) { - // Here we handle all the built-in functions instead of the ones we - // currently identified as problematic. - switch (node->getOp()) { - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - case EOpVectorEqual: - case EOpVectorNotEqual: - case EOpMod: - case EOpPow: - case EOpAtan: - case EOpMin: - case EOpMax: - case EOpClamp: - case EOpMix: - case EOpStep: - case EOpSmoothStep: - case EOpDistance: - case EOpDot: - case EOpCross: - case EOpFaceForward: - case EOpReflect: - case EOpRefract: - case EOpMul: - break; - default: - return true; - }; - const TIntermSequence& sequence = node->getSequence(); - // Right now we only handle built-in functions with two parameters. - if (sequence.size() != 2) - return true; - TIntermTyped* param1 = sequence[0]->getAsTyped(); - TIntermTyped* param2 = sequence[1]->getAsTyped(); - if (!param1 || !param2) - return true; - bool needToEmulate = mEmulator.SetFunctionCalled( - node->getOp(), param1->getType(), param2->getType()); - if (needToEmulate) - node->setUseEmulatedFunction(); - } - return true; - } - -private: - BuiltInFunctionEmulator& mEmulator; -}; - -} // anonymous namepsace - -BuiltInFunctionEmulator::BuiltInFunctionEmulator(ShShaderType shaderType) -{ - if (shaderType == SH_FRAGMENT_SHADER) { - mFunctionMask = kFunctionEmulationFragmentMask; - mFunctionSource = kFunctionEmulationFragmentSource; - } else { - mFunctionMask = kFunctionEmulationVertexMask; - mFunctionSource = kFunctionEmulationVertexSource; - } -} - -bool BuiltInFunctionEmulator::SetFunctionCalled( - TOperator op, const TType& param) -{ - TBuiltInFunction function = IdentifyFunction(op, param); - return SetFunctionCalled(function); -} - -bool BuiltInFunctionEmulator::SetFunctionCalled( - TOperator op, const TType& param1, const TType& param2) -{ - TBuiltInFunction function = IdentifyFunction(op, param1, param2); - return SetFunctionCalled(function); -} - -bool BuiltInFunctionEmulator::SetFunctionCalled( - BuiltInFunctionEmulator::TBuiltInFunction function) { - if (function == TFunctionUnknown || mFunctionMask[function] == false) - return false; - for (size_t i = 0; i < mFunctions.size(); ++i) { - if (mFunctions[i] == function) - return true; - } - mFunctions.push_back(function); - return true; -} - -void BuiltInFunctionEmulator::OutputEmulatedFunctionDefinition( - TInfoSinkBase& out, bool withPrecision) const -{ - if (mFunctions.size() == 0) - return; - out << "// BEGIN: Generated code for built-in function emulation\n\n"; - if (withPrecision) { - out << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n" - << "#define webgl_emu_precision highp\n" - << "#else\n" - << "#define webgl_emu_precision mediump\n" - << "#endif\n\n"; - } else { - out << "#define webgl_emu_precision\n\n"; - } - for (size_t i = 0; i < mFunctions.size(); ++i) { - out << mFunctionSource[mFunctions[i]] << "\n\n"; - } - out << "// END: Generated code for built-in function emulation\n\n"; -} - -BuiltInFunctionEmulator::TBuiltInFunction -BuiltInFunctionEmulator::IdentifyFunction( - TOperator op, const TType& param) -{ - if (param.getNominalSize() > 4) - return TFunctionUnknown; - unsigned int function = TFunctionUnknown; - switch (op) { - case EOpCos: - function = TFunctionCos1; - break; - case EOpLength: - function = TFunctionLength1; - break; - case EOpNormalize: - function = TFunctionNormalize1; - break; - default: - break; - } - if (function == TFunctionUnknown) - return TFunctionUnknown; - if (param.isVector()) - function += param.getNominalSize() - 1; - return static_cast(function); -} - -BuiltInFunctionEmulator::TBuiltInFunction -BuiltInFunctionEmulator::IdentifyFunction( - TOperator op, const TType& param1, const TType& param2) -{ - // Right now for all the emulated functions with two parameters, the two - // parameters have the same type. - if (param1.isVector() != param2.isVector() || - param1.getNominalSize() != param2.getNominalSize() || - param1.getNominalSize() > 4) - return TFunctionUnknown; - - unsigned int function = TFunctionUnknown; - switch (op) { - case EOpDistance: - function = TFunctionDistance1_1; - break; - case EOpDot: - function = TFunctionDot1_1; - break; - case EOpReflect: - function = TFunctionReflect1_1; - break; - default: - break; - } - if (function == TFunctionUnknown) - return TFunctionUnknown; - if (param1.isVector()) - function += param1.getNominalSize() - 1; - return static_cast(function); -} - -void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation( - TIntermNode* root) -{ - ASSERT(root); - - BuiltInFunctionEmulationMarker marker(*this); - root->traverse(&marker); -} - -void BuiltInFunctionEmulator::Cleanup() -{ - mFunctions.clear(); -} - -//static -TString BuiltInFunctionEmulator::GetEmulatedFunctionName( - const TString& name) -{ - ASSERT(name[name.length() - 1] == '('); - return "webgl_" + name.substr(0, name.length() - 1) + "_emu("; -} - diff --git a/src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.h b/src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.h deleted file mode 100644 index 0d904f41d0..0000000000 --- a/src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.h +++ /dev/null @@ -1,93 +0,0 @@ -// -// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ -#define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ - -#include "GLSLANG/ShaderLang.h" - -#include "compiler/InfoSink.h" -#include "compiler/intermediate.h" - -// -// This class decides which built-in functions need to be replaced with the -// emulated ones. -// It's only a workaround for OpenGL driver bugs, and isn't needed in general. -// -class BuiltInFunctionEmulator { -public: - BuiltInFunctionEmulator(ShShaderType shaderType); - // Records that a function is called by the shader and might needs to be - // emulated. If the function's group is not in mFunctionGroupFilter, this - // becomes an no-op. - // Returns true if the function call needs to be replaced with an emulated - // one. - bool SetFunctionCalled(TOperator op, const TType& param); - bool SetFunctionCalled( - TOperator op, const TType& param1, const TType& param2); - - // Output function emulation definition. This should be before any other - // shader source. - void OutputEmulatedFunctionDefinition(TInfoSinkBase& out, bool withPrecision) const; - - void MarkBuiltInFunctionsForEmulation(TIntermNode* root); - - void Cleanup(); - - // "name(" becomes "webgl_name_emu(". - static TString GetEmulatedFunctionName(const TString& name); - -private: - // - // Built-in functions. - // - enum TBuiltInFunction { - TFunctionCos1 = 0, // float cos(float); - TFunctionCos2, // vec2 cos(vec2); - TFunctionCos3, // vec3 cos(vec3); - TFunctionCos4, // vec4 cos(vec4); - - TFunctionDistance1_1, // float distance(float, float); - TFunctionDistance2_2, // vec2 distance(vec2, vec2); - TFunctionDistance3_3, // vec3 distance(vec3, vec3); - TFunctionDistance4_4, // vec4 distance(vec4, vec4); - - TFunctionDot1_1, // float dot(float, float); - TFunctionDot2_2, // vec2 dot(vec2, vec2); - TFunctionDot3_3, // vec3 dot(vec3, vec3); - TFunctionDot4_4, // vec4 dot(vec4, vec4); - - TFunctionLength1, // float length(float); - TFunctionLength2, // float length(vec2); - TFunctionLength3, // float length(vec3); - TFunctionLength4, // float length(vec4); - - TFunctionNormalize1, // float normalize(float); - TFunctionNormalize2, // vec2 normalize(vec2); - TFunctionNormalize3, // vec3 normalize(vec3); - TFunctionNormalize4, // vec4 normalize(vec4); - - TFunctionReflect1_1, // float reflect(float, float); - TFunctionReflect2_2, // vec2 reflect(vec2, vec2); - TFunctionReflect3_3, // vec3 reflect(vec3, vec3); - TFunctionReflect4_4, // vec4 reflect(vec4, vec4); - - TFunctionUnknown - }; - - TBuiltInFunction IdentifyFunction(TOperator op, const TType& param); - TBuiltInFunction IdentifyFunction( - TOperator op, const TType& param1, const TType& param2); - - bool SetFunctionCalled(TBuiltInFunction function); - - std::vector mFunctions; - - const bool* mFunctionMask; // a boolean flag for each function. - const char** mFunctionSource; -}; - -#endif // COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ diff --git a/src/3rdparty/angle/src/compiler/CodeGenGLSL.cpp b/src/3rdparty/angle/src/compiler/CodeGenGLSL.cpp deleted file mode 100644 index 226bf8f0fc..0000000000 --- a/src/3rdparty/angle/src/compiler/CodeGenGLSL.cpp +++ /dev/null @@ -1,34 +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. -// - -#include "compiler/TranslatorGLSL.h" -#include "compiler/TranslatorESSL.h" - -// -// This function must be provided to create the actual -// compile object used by higher level code. It returns -// a subclass of TCompiler. -// -TCompiler* ConstructCompiler( - ShShaderType type, ShShaderSpec spec, ShShaderOutput output) -{ - switch (output) { - case SH_GLSL_OUTPUT: - return new TranslatorGLSL(type, spec); - case SH_ESSL_OUTPUT: - return new TranslatorESSL(type, spec); - default: - return NULL; - } -} - -// -// Delete the compiler made by ConstructCompiler -// -void DeleteCompiler(TCompiler* compiler) -{ - delete compiler; -} diff --git a/src/3rdparty/angle/src/compiler/CodeGenHLSL.cpp b/src/3rdparty/angle/src/compiler/CodeGenHLSL.cpp deleted file mode 100644 index 637ccc5e37..0000000000 --- a/src/3rdparty/angle/src/compiler/CodeGenHLSL.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/TranslatorHLSL.h" - -// -// This function must be provided to create the actual -// compile object used by higher level code. It returns -// a subclass of TCompiler. -// -TCompiler* ConstructCompiler( - ShShaderType type, ShShaderSpec spec, ShShaderOutput output) -{ - switch (output) - { - case SH_HLSL9_OUTPUT: - case SH_HLSL11_OUTPUT: - return new TranslatorHLSL(type, spec, output); - default: - return NULL; - } -} - -// -// Delete the compiler made by ConstructCompiler -// -void DeleteCompiler(TCompiler* compiler) -{ - delete compiler; -} diff --git a/src/3rdparty/angle/src/compiler/Common.h b/src/3rdparty/angle/src/compiler/Common.h deleted file mode 100644 index 46f9440fff..0000000000 --- a/src/3rdparty/angle/src/compiler/Common.h +++ /dev/null @@ -1,77 +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. -// - -#ifndef _COMMON_INCLUDED_ -#define _COMMON_INCLUDED_ - -#include -#include -#include -#include - -#include "compiler/PoolAlloc.h" - -struct TSourceLoc { - int first_file; - int first_line; - int last_file; - int last_line; -}; - -// -// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. -// -#define POOL_ALLOCATOR_NEW_DELETE() \ - void* operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ - void* operator new(size_t, void *_Where) { return (_Where); } \ - void operator delete(void*) { } \ - void operator delete(void *, void *) { } \ - void* operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ - void* operator new[](size_t, void *_Where) { return (_Where); } \ - void operator delete[](void*) { } \ - void operator delete[](void *, void *) { } - -// -// Pool version of string. -// -typedef pool_allocator TStringAllocator; -typedef std::basic_string , TStringAllocator> TString; -typedef std::basic_ostringstream, TStringAllocator> TStringStream; -inline TString* NewPoolTString(const char* s) -{ - void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TString)); - return new(memory) TString(s); -} - -// -// Persistent string memory. Should only be used for strings that survive -// across compiles. -// -#define TPersistString std::string -#define TPersistStringStream std::ostringstream - -// -// Pool allocator versions of vectors, lists, and maps -// -template class TVector : public std::vector > { -public: - typedef typename std::vector >::size_type size_type; - TVector() : std::vector >() {} - TVector(const pool_allocator& a) : std::vector >(a) {} - TVector(size_type i): std::vector >(i) {} -}; - -template > -class TMap : public std::map > > { -public: - typedef pool_allocator > tAllocator; - - TMap() : std::map() {} - // use correct two-stage name lookup supported in gcc 3.4 and above - TMap(const tAllocator& a) : std::map(std::map::key_compare(), a) {} -}; - -#endif // _COMMON_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/Compiler.cpp b/src/3rdparty/angle/src/compiler/Compiler.cpp deleted file mode 100644 index ee64057ac4..0000000000 --- a/src/3rdparty/angle/src/compiler/Compiler.cpp +++ /dev/null @@ -1,433 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/BuiltInFunctionEmulator.h" -#include "compiler/DetectCallDepth.h" -#include "compiler/ForLoopUnroll.h" -#include "compiler/Initialize.h" -#include "compiler/InitializeGLPosition.h" -#include "compiler/InitializeParseContext.h" -#include "compiler/MapLongVariableNames.h" -#include "compiler/ParseHelper.h" -#include "compiler/RenameFunction.h" -#include "compiler/ShHandle.h" -#include "compiler/ValidateLimitations.h" -#include "compiler/VariablePacker.h" -#include "compiler/depgraph/DependencyGraph.h" -#include "compiler/depgraph/DependencyGraphOutput.h" -#include "compiler/timing/RestrictFragmentShaderTiming.h" -#include "compiler/timing/RestrictVertexShaderTiming.h" -#include "third_party/compiler/ArrayBoundsClamper.h" - -bool isWebGLBasedSpec(ShShaderSpec spec) -{ - return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC; -} - -namespace { -class TScopedPoolAllocator { -public: - TScopedPoolAllocator(TPoolAllocator* allocator) : mAllocator(allocator) { - mAllocator->push(); - SetGlobalPoolAllocator(mAllocator); - } - ~TScopedPoolAllocator() { - SetGlobalPoolAllocator(NULL); - mAllocator->pop(); - } - -private: - TPoolAllocator* mAllocator; -}; - -class TScopedSymbolTableLevel { -public: - TScopedSymbolTableLevel(TSymbolTable* table) : mTable(table) { - ASSERT(mTable->atBuiltInLevel()); - mTable->push(); - } - ~TScopedSymbolTableLevel() { - while (!mTable->atBuiltInLevel()) - mTable->pop(); - } - -private: - TSymbolTable* mTable; -}; -} // namespace - -TShHandleBase::TShHandleBase() { - allocator.push(); - SetGlobalPoolAllocator(&allocator); -} - -TShHandleBase::~TShHandleBase() { - SetGlobalPoolAllocator(NULL); - allocator.popAll(); -} - -TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec) - : shaderType(type), - shaderSpec(spec), - maxUniformVectors(0), - maxExpressionComplexity(0), - maxCallStackDepth(0), - fragmentPrecisionHigh(false), - clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC), - builtInFunctionEmulator(type) -{ - longNameMap = LongNameMap::GetInstance(); -} - -TCompiler::~TCompiler() -{ - ASSERT(longNameMap); - longNameMap->Release(); -} - -bool TCompiler::Init(const ShBuiltInResources& resources) -{ - maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ? - resources.MaxVertexUniformVectors : - resources.MaxFragmentUniformVectors; - maxExpressionComplexity = resources.MaxExpressionComplexity; - maxCallStackDepth = resources.MaxCallStackDepth; - - SetGlobalPoolAllocator(&allocator); - - // Generate built-in symbol table. - if (!InitBuiltInSymbolTable(resources)) - return false; - InitExtensionBehavior(resources, extensionBehavior); - fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1; - - arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy); - clampingStrategy = resources.ArrayIndexClampingStrategy; - - hashFunction = resources.HashFunction; - - return true; -} - -bool TCompiler::compile(const char* const shaderStrings[], - size_t numStrings, - int compileOptions) -{ - TScopedPoolAllocator scopedAlloc(&allocator); - clearResults(); - - if (numStrings == 0) - return true; - - // If compiling for WebGL, validate loop and indexing as well. - if (isWebGLBasedSpec(shaderSpec)) - compileOptions |= SH_VALIDATE_LOOP_INDEXING; - - // First string is path of source file if flag is set. The actual source follows. - const char* sourcePath = NULL; - size_t firstSource = 0; - if (compileOptions & SH_SOURCE_PATH) - { - sourcePath = shaderStrings[0]; - ++firstSource; - } - - TIntermediate intermediate(infoSink); - TParseContext parseContext(symbolTable, extensionBehavior, intermediate, - shaderType, shaderSpec, compileOptions, true, - sourcePath, infoSink); - parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh; - SetGlobalParseContext(&parseContext); - - // We preserve symbols at the built-in level from compile-to-compile. - // Start pushing the user-defined symbols at global level. - TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable); - - // Parse shader. - bool success = - (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) && - (parseContext.treeRoot != NULL); - if (success) { - TIntermNode* root = parseContext.treeRoot; - success = intermediate.postProcess(root); - - if (success) - success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0); - - if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING)) - success = validateLimitations(root); - - if (success && (compileOptions & SH_TIMING_RESTRICTIONS)) - success = enforceTimingRestrictions(root, (compileOptions & SH_DEPENDENCY_GRAPH) != 0); - - if (success && shaderSpec == SH_CSS_SHADERS_SPEC) - rewriteCSSShader(root); - - // Unroll for-loop markup needs to happen after validateLimitations pass. - if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX)) - ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(root); - - // Built-in function emulation needs to happen after validateLimitations pass. - if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS)) - builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root); - - // Clamping uniform array bounds needs to happen after validateLimitations pass. - if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)) - arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root); - - // Disallow expressions deemed too complex. - if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY)) - success = limitExpressionComplexity(root); - - // Call mapLongVariableNames() before collectAttribsUniforms() so in - // collectAttribsUniforms() we already have the mapped symbol names and - // we could composite mapped and original variable names. - // Also, if we hash all the names, then no need to do this for long names. - if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL) - mapLongVariableNames(root); - - if (success && shaderType == SH_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION)) { - InitializeGLPosition initGLPosition; - root->traverse(&initGLPosition); - } - - if (success && (compileOptions & SH_VARIABLES)) { - collectVariables(root); - if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) { - success = enforcePackingRestrictions(); - if (!success) { - infoSink.info.prefix(EPrefixError); - infoSink.info << "too many uniforms"; - } - } - } - - if (success && (compileOptions & SH_INTERMEDIATE_TREE)) - intermediate.outputTree(root); - - if (success && (compileOptions & SH_OBJECT_CODE)) - translate(root); - } - - // Cleanup memory. - intermediate.remove(parseContext.treeRoot); - - return success; -} - -bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources) -{ - compileResources = resources; - - assert(symbolTable.isEmpty()); - symbolTable.push(); - - TPublicType integer; - integer.type = EbtInt; - integer.size = 1; - integer.matrix = false; - integer.array = false; - - TPublicType floatingPoint; - floatingPoint.type = EbtFloat; - floatingPoint.size = 1; - floatingPoint.matrix = false; - floatingPoint.array = false; - - TPublicType sampler; - sampler.size = 1; - sampler.matrix = false; - sampler.array = false; - - switch(shaderType) - { - case SH_FRAGMENT_SHADER: - symbolTable.setDefaultPrecision(integer, EbpMedium); - break; - case SH_VERTEX_SHADER: - symbolTable.setDefaultPrecision(integer, EbpHigh); - symbolTable.setDefaultPrecision(floatingPoint, EbpHigh); - break; - default: assert(false && "Language not supported"); - } - // We set defaults for all the sampler types, even those that are - // only available if an extension exists. - for (int samplerType = EbtGuardSamplerBegin + 1; - samplerType < EbtGuardSamplerEnd; ++samplerType) { - sampler.type = static_cast(samplerType); - symbolTable.setDefaultPrecision(sampler, EbpLow); - } - - InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable); - - IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable); - - return true; -} - -void TCompiler::clearResults() -{ - arrayBoundsClamper.Cleanup(); - infoSink.info.erase(); - infoSink.obj.erase(); - infoSink.debug.erase(); - - attribs.clear(); - uniforms.clear(); - varyings.clear(); - - builtInFunctionEmulator.Cleanup(); - - nameMap.clear(); -} - -bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth) -{ - DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth); - root->traverse(&detect); - switch (detect.detectCallDepth()) { - case DetectCallDepth::kErrorNone: - return true; - case DetectCallDepth::kErrorMissingMain: - infoSink.info.prefix(EPrefixError); - infoSink.info << "Missing main()"; - return false; - case DetectCallDepth::kErrorRecursion: - infoSink.info.prefix(EPrefixError); - infoSink.info << "Function recursion detected"; - return false; - case DetectCallDepth::kErrorMaxDepthExceeded: - infoSink.info.prefix(EPrefixError); - infoSink.info << "Function call stack too deep"; - return false; - default: - UNREACHABLE(); - return false; - } -} - -void TCompiler::rewriteCSSShader(TIntermNode* root) -{ - RenameFunction renamer("main(", "css_main("); - root->traverse(&renamer); -} - -bool TCompiler::validateLimitations(TIntermNode* root) { - ValidateLimitations validate(shaderType, infoSink.info); - root->traverse(&validate); - return validate.numErrors() == 0; -} - -bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph) -{ - if (shaderSpec != SH_WEBGL_SPEC) { - infoSink.info << "Timing restrictions must be enforced under the WebGL spec."; - return false; - } - - if (shaderType == SH_FRAGMENT_SHADER) { - TDependencyGraph graph(root); - - // Output any errors first. - bool success = enforceFragmentShaderTimingRestrictions(graph); - - // Then, output the dependency graph. - if (outputGraph) { - TDependencyGraphOutput output(infoSink.info); - output.outputAllSpanningTrees(graph); - } - - return success; - } - else { - return enforceVertexShaderTimingRestrictions(root); - } -} - -bool TCompiler::limitExpressionComplexity(TIntermNode* root) -{ - TIntermTraverser traverser; - root->traverse(&traverser); - TDependencyGraph graph(root); - - for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls(); - iter != graph.endUserDefinedFunctionCalls(); - ++iter) - { - TGraphFunctionCall* samplerSymbol = *iter; - TDependencyGraphTraverser graphTraverser; - samplerSymbol->traverse(&graphTraverser); - } - - if (traverser.getMaxDepth() > maxExpressionComplexity) { - infoSink.info << "Expression too complex."; - return false; - } - return true; -} - -bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph) -{ - RestrictFragmentShaderTiming restrictor(infoSink.info); - restrictor.enforceRestrictions(graph); - return restrictor.numErrors() == 0; -} - -bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root) -{ - RestrictVertexShaderTiming restrictor(infoSink.info); - restrictor.enforceRestrictions(root); - return restrictor.numErrors() == 0; -} - -void TCompiler::collectVariables(TIntermNode* root) -{ - CollectVariables collect(attribs, uniforms, varyings, hashFunction); - root->traverse(&collect); -} - -bool TCompiler::enforcePackingRestrictions() -{ - VariablePacker packer; - return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, uniforms); -} - -void TCompiler::mapLongVariableNames(TIntermNode* root) -{ - ASSERT(longNameMap); - MapLongVariableNames map(longNameMap); - root->traverse(&map); -} - -int TCompiler::getMappedNameMaxLength() const -{ - return MAX_SHORTENED_IDENTIFIER_SIZE + 1; -} - -const TExtensionBehavior& TCompiler::getExtensionBehavior() const -{ - return extensionBehavior; -} - -const ShBuiltInResources& TCompiler::getResources() const -{ - return compileResources; -} - -const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const -{ - return arrayBoundsClamper; -} - -ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const -{ - return clampingStrategy; -} - -const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const -{ - return builtInFunctionEmulator; -} diff --git a/src/3rdparty/angle/src/compiler/ConstantUnion.h b/src/3rdparty/angle/src/compiler/ConstantUnion.h deleted file mode 100644 index b1e37885f9..0000000000 --- a/src/3rdparty/angle/src/compiler/ConstantUnion.h +++ /dev/null @@ -1,257 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef _CONSTANT_UNION_INCLUDED_ -#define _CONSTANT_UNION_INCLUDED_ - -#include - -class ConstantUnion { -public: - POOL_ALLOCATOR_NEW_DELETE(); - ConstantUnion() - { - iConst = 0; - type = EbtVoid; - } - - void setIConst(int i) {iConst = i; type = EbtInt; } - void setFConst(float f) {fConst = f; type = EbtFloat; } - void setBConst(bool b) {bConst = b; type = EbtBool; } - - int getIConst() { return iConst; } - float getFConst() { return fConst; } - bool getBConst() { return bConst; } - int getIConst() const { return iConst; } - float getFConst() const { return fConst; } - bool getBConst() const { return bConst; } - - bool operator==(const int i) const - { - return i == iConst; - } - - bool operator==(const float f) const - { - return f == fConst; - } - - bool operator==(const bool b) const - { - return b == bConst; - } - - bool operator==(const ConstantUnion& constant) const - { - if (constant.type != type) - return false; - - switch (type) { - case EbtInt: - return constant.iConst == iConst; - case EbtFloat: - return constant.fConst == fConst; - case EbtBool: - return constant.bConst == bConst; - default: - return false; - } - } - - bool operator!=(const int i) const - { - return !operator==(i); - } - - bool operator!=(const float f) const - { - return !operator==(f); - } - - bool operator!=(const bool b) const - { - return !operator==(b); - } - - bool operator!=(const ConstantUnion& constant) const - { - return !operator==(constant); - } - - bool operator>(const ConstantUnion& constant) const - { - assert(type == constant.type); - switch (type) { - case EbtInt: - return iConst > constant.iConst; - case EbtFloat: - return fConst > constant.fConst; - default: - return false; // Invalid operation, handled at semantic analysis - } - } - - bool operator<(const ConstantUnion& constant) const - { - assert(type == constant.type); - switch (type) { - case EbtInt: - return iConst < constant.iConst; - case EbtFloat: - return fConst < constant.fConst; - default: - return false; // Invalid operation, handled at semantic analysis - } - } - - ConstantUnion operator+(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst + constant.iConst); break; - case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - ConstantUnion operator-(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst - constant.iConst); break; - case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - ConstantUnion operator*(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst * constant.iConst); break; - case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - ConstantUnion operator%(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst % constant.iConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - ConstantUnion operator>>(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - ConstantUnion operator<<(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - ConstantUnion operator&(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - ConstantUnion operator|(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst | constant.iConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - ConstantUnion operator^(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - ConstantUnion operator&&(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtBool: returnValue.setBConst(bConst && constant.bConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - ConstantUnion operator||(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtBool: returnValue.setBConst(bConst || constant.bConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TBasicType getType() const { return type; } -private: - - union { - int iConst; // used for ivec, scalar ints - bool bConst; // used for bvec, scalar bools - float fConst; // used for vec, mat, scalar floats - } ; - - TBasicType type; -}; - -#endif // _CONSTANT_UNION_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/DetectCallDepth.cpp b/src/3rdparty/angle/src/compiler/DetectCallDepth.cpp deleted file mode 100644 index 60df52c715..0000000000 --- a/src/3rdparty/angle/src/compiler/DetectCallDepth.cpp +++ /dev/null @@ -1,185 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/DetectCallDepth.h" -#include "compiler/InfoSink.h" - -DetectCallDepth::FunctionNode::FunctionNode(const TString& fname) - : name(fname), - visit(PreVisit) -{ -} - -const TString& DetectCallDepth::FunctionNode::getName() const -{ - return name; -} - -void DetectCallDepth::FunctionNode::addCallee( - DetectCallDepth::FunctionNode* callee) -{ - for (size_t i = 0; i < callees.size(); ++i) { - if (callees[i] == callee) - return; - } - callees.push_back(callee); -} - -int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDepth, int depth) -{ - ASSERT(visit == PreVisit); - ASSERT(detectCallDepth); - - int maxDepth = depth; - visit = InVisit; - for (size_t i = 0; i < callees.size(); ++i) { - switch (callees[i]->visit) { - case InVisit: - // cycle detected, i.e., recursion detected. - return kInfiniteCallDepth; - case PostVisit: - break; - case PreVisit: { - // Check before we recurse so we don't go too depth - if (detectCallDepth->checkExceedsMaxDepth(depth)) - return depth; - int callDepth = callees[i]->detectCallDepth(detectCallDepth, depth + 1); - // Check after we recurse so we can exit immediately and provide info. - if (detectCallDepth->checkExceedsMaxDepth(callDepth)) { - detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName(); - return callDepth; - } - maxDepth = std::max(callDepth, maxDepth); - break; - } - default: - UNREACHABLE(); - break; - } - } - visit = PostVisit; - return maxDepth; -} - -void DetectCallDepth::FunctionNode::reset() -{ - visit = PreVisit; -} - -DetectCallDepth::DetectCallDepth(TInfoSink& infoSink, bool limitCallStackDepth, int maxCallStackDepth) - : TIntermTraverser(true, false, true, false), - currentFunction(NULL), - infoSink(infoSink), - maxDepth(limitCallStackDepth ? maxCallStackDepth : FunctionNode::kInfiniteCallDepth) -{ -} - -DetectCallDepth::~DetectCallDepth() -{ - for (size_t i = 0; i < functions.size(); ++i) - delete functions[i]; -} - -bool DetectCallDepth::visitAggregate(Visit visit, TIntermAggregate* node) -{ - switch (node->getOp()) - { - case EOpPrototype: - // Function declaration. - // Don't add FunctionNode here because node->getName() is the - // unmangled function name. - break; - case EOpFunction: { - // Function definition. - if (visit == PreVisit) { - currentFunction = findFunctionByName(node->getName()); - if (currentFunction == NULL) { - currentFunction = new FunctionNode(node->getName()); - functions.push_back(currentFunction); - } - } else if (visit == PostVisit) { - currentFunction = NULL; - } - break; - } - case EOpFunctionCall: { - // Function call. - if (visit == PreVisit) { - FunctionNode* func = findFunctionByName(node->getName()); - if (func == NULL) { - func = new FunctionNode(node->getName()); - functions.push_back(func); - } - if (currentFunction) - currentFunction->addCallee(func); - } - break; - } - default: - break; - } - return true; -} - -bool DetectCallDepth::checkExceedsMaxDepth(int depth) -{ - return depth >= maxDepth; -} - -void DetectCallDepth::resetFunctionNodes() -{ - for (size_t i = 0; i < functions.size(); ++i) { - functions[i]->reset(); - } -} - -DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepthForFunction(FunctionNode* func) -{ - currentFunction = NULL; - resetFunctionNodes(); - - int maxCallDepth = func->detectCallDepth(this, 1); - - if (maxCallDepth == FunctionNode::kInfiniteCallDepth) - return kErrorRecursion; - - if (maxCallDepth >= maxDepth) - return kErrorMaxDepthExceeded; - - return kErrorNone; -} - -DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepth() -{ - if (maxDepth != FunctionNode::kInfiniteCallDepth) { - // Check all functions because the driver may fail on them - // TODO: Before detectingRecursion, strip unused functions. - for (size_t i = 0; i < functions.size(); ++i) { - ErrorCode error = detectCallDepthForFunction(functions[i]); - if (error != kErrorNone) - return error; - } - } else { - FunctionNode* main = findFunctionByName("main("); - if (main == NULL) - return kErrorMissingMain; - - return detectCallDepthForFunction(main); - } - - return kErrorNone; -} - -DetectCallDepth::FunctionNode* DetectCallDepth::findFunctionByName( - const TString& name) -{ - for (size_t i = 0; i < functions.size(); ++i) { - if (functions[i]->getName() == name) - return functions[i]; - } - return NULL; -} - diff --git a/src/3rdparty/angle/src/compiler/DetectCallDepth.h b/src/3rdparty/angle/src/compiler/DetectCallDepth.h deleted file mode 100644 index 89e85f88f6..0000000000 --- a/src/3rdparty/angle/src/compiler/DetectCallDepth.h +++ /dev/null @@ -1,80 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_DETECT_RECURSION_H_ -#define COMPILER_DETECT_RECURSION_H_ - -#include "GLSLANG/ShaderLang.h" - -#include -#include "compiler/intermediate.h" -#include "compiler/VariableInfo.h" - -class TInfoSink; - -// Traverses intermediate tree to detect function recursion. -class DetectCallDepth : public TIntermTraverser { -public: - enum ErrorCode { - kErrorMissingMain, - kErrorRecursion, - kErrorMaxDepthExceeded, - kErrorNone - }; - - DetectCallDepth(TInfoSink& infoSync, bool limitCallStackDepth, int maxCallStackDepth); - ~DetectCallDepth(); - - virtual bool visitAggregate(Visit, TIntermAggregate*); - - bool checkExceedsMaxDepth(int depth); - - ErrorCode detectCallDepth(); - -private: - class FunctionNode { - public: - static const int kInfiniteCallDepth = INT_MAX; - - FunctionNode(const TString& fname); - - const TString& getName() const; - - // If a function is already in the callee list, this becomes a no-op. - void addCallee(FunctionNode* callee); - - // Returns kInifinityCallDepth if recursive function calls are detected. - int detectCallDepth(DetectCallDepth* detectCallDepth, int depth); - - // Reset state. - void reset(); - - private: - // mangled function name is unique. - TString name; - - // functions that are directly called by this function. - TVector callees; - - Visit visit; - }; - - ErrorCode detectCallDepthForFunction(FunctionNode* func); - FunctionNode* findFunctionByName(const TString& name); - void resetFunctionNodes(); - - TInfoSink& getInfoSink() { return infoSink; } - - TVector functions; - FunctionNode* currentFunction; - TInfoSink& infoSink; - int maxDepth; - - DetectCallDepth(const DetectCallDepth&); - void operator=(const DetectCallDepth&); -}; - -#endif // COMPILER_DETECT_RECURSION_H_ diff --git a/src/3rdparty/angle/src/compiler/DetectDiscontinuity.cpp b/src/3rdparty/angle/src/compiler/DetectDiscontinuity.cpp deleted file mode 100644 index 7c3b68a0b3..0000000000 --- a/src/3rdparty/angle/src/compiler/DetectDiscontinuity.cpp +++ /dev/null @@ -1,139 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Contains analysis utilities for dealing with HLSL's lack of support for -// the use of intrinsic functions which (implicitly or explicitly) compute -// gradients of functions with discontinuities. -// - -#include "compiler/DetectDiscontinuity.h" - -#include "compiler/ParseHelper.h" - -namespace sh -{ -bool DetectLoopDiscontinuity::traverse(TIntermNode *node) -{ - mLoopDepth = 0; - mLoopDiscontinuity = false; - node->traverse(this); - return mLoopDiscontinuity; -} - -bool DetectLoopDiscontinuity::visitLoop(Visit visit, TIntermLoop *loop) -{ - if (visit == PreVisit) - { - ++mLoopDepth; - } - else if (visit == PostVisit) - { - --mLoopDepth; - } - - return true; -} - -bool DetectLoopDiscontinuity::visitBranch(Visit visit, TIntermBranch *node) -{ - if (mLoopDiscontinuity) - { - return false; - } - - if (!mLoopDepth) - { - return true; - } - - switch (node->getFlowOp()) - { - case EOpKill: - break; - case EOpBreak: - case EOpContinue: - case EOpReturn: - mLoopDiscontinuity = true; - break; - default: UNREACHABLE(); - } - - return !mLoopDiscontinuity; -} - -bool DetectLoopDiscontinuity::visitAggregate(Visit visit, TIntermAggregate *node) -{ - return !mLoopDiscontinuity; -} - -bool containsLoopDiscontinuity(TIntermNode *node) -{ - DetectLoopDiscontinuity detectLoopDiscontinuity; - return detectLoopDiscontinuity.traverse(node); -} - -bool DetectGradientOperation::traverse(TIntermNode *node) -{ - mGradientOperation = false; - node->traverse(this); - return mGradientOperation; -} - -bool DetectGradientOperation::visitUnary(Visit visit, TIntermUnary *node) -{ - if (mGradientOperation) - { - return false; - } - - switch (node->getOp()) - { - case EOpDFdx: - case EOpDFdy: - mGradientOperation = true; - default: - break; - } - - return !mGradientOperation; -} - -bool DetectGradientOperation::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (mGradientOperation) - { - return false; - } - - if (node->getOp() == EOpFunctionCall) - { - if (!node->isUserDefined()) - { - TString name = TFunction::unmangleName(node->getName()); - - if (name == "texture2D" || - name == "texture2DProj" || - name == "textureCube") - { - mGradientOperation = true; - } - } - else - { - // When a user defined function is called, we have to - // conservatively assume it to contain gradient operations - mGradientOperation = true; - } - } - - return !mGradientOperation; -} - -bool containsGradientOperation(TIntermNode *node) -{ - DetectGradientOperation detectGradientOperation; - return detectGradientOperation.traverse(node); -} -} diff --git a/src/3rdparty/angle/src/compiler/DetectDiscontinuity.h b/src/3rdparty/angle/src/compiler/DetectDiscontinuity.h deleted file mode 100644 index e5520bd5b0..0000000000 --- a/src/3rdparty/angle/src/compiler/DetectDiscontinuity.h +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Contains analysis utilities for dealing with HLSL's lack of support for -// the use of intrinsic functions which (implicitly or explicitly) compute -// gradients of functions with discontinuities. -// - -#ifndef COMPILER_DETECTDISCONTINUITY_H_ -#define COMPILER_DETECTDISCONTINUITY_H_ - -#include "compiler/intermediate.h" - -namespace sh -{ -// Checks whether a loop can run for a variable number of iterations -class DetectLoopDiscontinuity : public TIntermTraverser -{ - public: - bool traverse(TIntermNode *node); - - protected: - bool visitBranch(Visit visit, TIntermBranch *node); - bool visitLoop(Visit visit, TIntermLoop *loop); - bool visitAggregate(Visit visit, TIntermAggregate *node); - - int mLoopDepth; - bool mLoopDiscontinuity; -}; - -bool containsLoopDiscontinuity(TIntermNode *node); - -// Checks for intrinsic functions which compute gradients -class DetectGradientOperation : public TIntermTraverser -{ - public: - bool traverse(TIntermNode *node); - - protected: - bool visitUnary(Visit visit, TIntermUnary *node); - bool visitAggregate(Visit visit, TIntermAggregate *node); - - bool mGradientOperation; -}; - -bool containsGradientOperation(TIntermNode *node); - -} - -#endif // COMPILER_DETECTDISCONTINUITY_H_ diff --git a/src/3rdparty/angle/src/compiler/DetectRecursion.cpp b/src/3rdparty/angle/src/compiler/DetectRecursion.cpp deleted file mode 100644 index c09780dd92..0000000000 --- a/src/3rdparty/angle/src/compiler/DetectRecursion.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/DetectRecursion.h" - -DetectRecursion::FunctionNode::FunctionNode(const TString& fname) - : name(fname), - visit(PreVisit) -{ -} - -const TString& DetectRecursion::FunctionNode::getName() const -{ - return name; -} - -void DetectRecursion::FunctionNode::addCallee( - DetectRecursion::FunctionNode* callee) -{ - for (size_t i = 0; i < callees.size(); ++i) { - if (callees[i] == callee) - return; - } - callees.push_back(callee); -} - -bool DetectRecursion::FunctionNode::detectRecursion() -{ - ASSERT(visit == PreVisit); - visit = InVisit; - for (size_t i = 0; i < callees.size(); ++i) { - switch (callees[i]->visit) { - case InVisit: - // cycle detected, i.e., recursion detected. - return true; - case PostVisit: - break; - case PreVisit: { - bool recursion = callees[i]->detectRecursion(); - if (recursion) - return true; - break; - } - default: - UNREACHABLE(); - break; - } - } - visit = PostVisit; - return false; -} - -DetectRecursion::DetectRecursion() - : currentFunction(NULL) -{ -} - -DetectRecursion::~DetectRecursion() -{ - for (size_t i = 0; i < functions.size(); ++i) - delete functions[i]; -} - -bool DetectRecursion::visitAggregate(Visit visit, TIntermAggregate* node) -{ - switch (node->getOp()) - { - case EOpPrototype: - // Function declaration. - // Don't add FunctionNode here because node->getName() is the - // unmangled function name. - break; - case EOpFunction: { - // Function definition. - if (visit == PreVisit) { - currentFunction = findFunctionByName(node->getName()); - if (currentFunction == NULL) { - currentFunction = new FunctionNode(node->getName()); - functions.push_back(currentFunction); - } - } - break; - } - case EOpFunctionCall: { - // Function call. - if (visit == PreVisit) { - ASSERT(currentFunction != NULL); - FunctionNode* func = findFunctionByName(node->getName()); - if (func == NULL) { - func = new FunctionNode(node->getName()); - functions.push_back(func); - } - currentFunction->addCallee(func); - } - break; - } - default: - break; - } - return true; -} - -DetectRecursion::ErrorCode DetectRecursion::detectRecursion() -{ - FunctionNode* main = findFunctionByName("main("); - if (main == NULL) - return kErrorMissingMain; - if (main->detectRecursion()) - return kErrorRecursion; - return kErrorNone; -} - -DetectRecursion::FunctionNode* DetectRecursion::findFunctionByName( - const TString& name) -{ - for (size_t i = 0; i < functions.size(); ++i) { - if (functions[i]->getName() == name) - return functions[i]; - } - return NULL; -} - diff --git a/src/3rdparty/angle/src/compiler/DetectRecursion.h b/src/3rdparty/angle/src/compiler/DetectRecursion.h deleted file mode 100644 index bbac79dc9c..0000000000 --- a/src/3rdparty/angle/src/compiler/DetectRecursion.h +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_DETECT_RECURSION_H_ -#define COMPILER_DETECT_RECURSION_H_ - -#include "GLSLANG/ShaderLang.h" - -#include "compiler/intermediate.h" -#include "compiler/VariableInfo.h" - -// Traverses intermediate tree to detect function recursion. -class DetectRecursion : public TIntermTraverser { -public: - enum ErrorCode { - kErrorMissingMain, - kErrorRecursion, - kErrorNone - }; - - DetectRecursion(); - ~DetectRecursion(); - - virtual bool visitAggregate(Visit, TIntermAggregate*); - - ErrorCode detectRecursion(); - -private: - class FunctionNode { - public: - FunctionNode(const TString& fname); - - const TString& getName() const; - - // If a function is already in the callee list, this becomes a no-op. - void addCallee(FunctionNode* callee); - - // Return true if recursive function calls are detected. - bool detectRecursion(); - - private: - // mangled function name is unique. - TString name; - - // functions that are directly called by this function. - TVector callees; - - Visit visit; - }; - - FunctionNode* findFunctionByName(const TString& name); - - TVector functions; - FunctionNode* currentFunction; -}; - -#endif // COMPILER_DETECT_RECURSION_H_ diff --git a/src/3rdparty/angle/src/compiler/Diagnostics.cpp b/src/3rdparty/angle/src/compiler/Diagnostics.cpp deleted file mode 100644 index 8a38c41a65..0000000000 --- a/src/3rdparty/angle/src/compiler/Diagnostics.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/Diagnostics.h" - -#include "compiler/debug.h" -#include "compiler/InfoSink.h" -#include "compiler/preprocessor/SourceLocation.h" - -TDiagnostics::TDiagnostics(TInfoSink& infoSink) : - mInfoSink(infoSink), - mNumErrors(0), - mNumWarnings(0) -{ -} - -TDiagnostics::~TDiagnostics() -{ -} - -void TDiagnostics::writeInfo(Severity severity, - const pp::SourceLocation& loc, - const std::string& reason, - const std::string& token, - const std::string& extra) -{ - TPrefixType prefix = EPrefixNone; - switch (severity) - { - case ERROR: - ++mNumErrors; - prefix = EPrefixError; - break; - case WARNING: - ++mNumWarnings; - prefix = EPrefixWarning; - break; - default: - UNREACHABLE(); - break; - } - - TInfoSinkBase& sink = mInfoSink.info; - /* VC++ format: file(linenum) : error #: 'token' : extrainfo */ - sink.prefix(prefix); - sink.location(loc.file, loc.line); - sink << "'" << token << "' : " << reason << " " << extra << "\n"; -} - -void TDiagnostics::writeDebug(const std::string& str) -{ - mInfoSink.debug << str; -} - -void TDiagnostics::print(ID id, - const pp::SourceLocation& loc, - const std::string& text) -{ - writeInfo(severity(id), loc, message(id), text, ""); -} diff --git a/src/3rdparty/angle/src/compiler/Diagnostics.h b/src/3rdparty/angle/src/compiler/Diagnostics.h deleted file mode 100644 index cb71bb1204..0000000000 --- a/src/3rdparty/angle/src/compiler/Diagnostics.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_DIAGNOSTICS_H_ -#define COMPILER_DIAGNOSTICS_H_ - -#include "compiler/preprocessor/DiagnosticsBase.h" - -class TInfoSink; - -class TDiagnostics : public pp::Diagnostics -{ - public: - TDiagnostics(TInfoSink& infoSink); - virtual ~TDiagnostics(); - - TInfoSink& infoSink() { return mInfoSink; } - - int numErrors() const { return mNumErrors; } - int numWarnings() const { return mNumWarnings; } - - void writeInfo(Severity severity, - const pp::SourceLocation& loc, - const std::string& reason, - const std::string& token, - const std::string& extra); - - void writeDebug(const std::string& str); - - protected: - virtual void print(ID id, - const pp::SourceLocation& loc, - const std::string& text); - - private: - TInfoSink& mInfoSink; - int mNumErrors; - int mNumWarnings; -}; - -#endif // COMPILER_DIAGNOSTICS_H_ diff --git a/src/3rdparty/angle/src/compiler/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/DirectiveHandler.cpp deleted file mode 100644 index d1f6ab3af5..0000000000 --- a/src/3rdparty/angle/src/compiler/DirectiveHandler.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/DirectiveHandler.h" - -#include - -#include "compiler/debug.h" -#include "compiler/Diagnostics.h" - -static TBehavior getBehavior(const std::string& str) -{ - static const std::string kRequire("require"); - static const std::string kEnable("enable"); - static const std::string kDisable("disable"); - static const std::string kWarn("warn"); - - if (str == kRequire) return EBhRequire; - else if (str == kEnable) return EBhEnable; - else if (str == kDisable) return EBhDisable; - else if (str == kWarn) return EBhWarn; - return EBhUndefined; -} - -TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior, - TDiagnostics& diagnostics) - : mExtensionBehavior(extBehavior), - mDiagnostics(diagnostics) -{ -} - -TDirectiveHandler::~TDirectiveHandler() -{ -} - -void TDirectiveHandler::handleError(const pp::SourceLocation& loc, - const std::string& msg) -{ - mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc, msg, "", ""); -} - -void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc, - const std::string& name, - const std::string& value) -{ - static const std::string kSTDGL("STDGL"); - static const std::string kOptimize("optimize"); - static const std::string kDebug("debug"); - static const std::string kOn("on"); - static const std::string kOff("off"); - - bool invalidValue = false; - if (name == kSTDGL) - { - // The STDGL pragma is used to reserve pragmas for use by future - // revisions of GLSL. Ignore it. - return; - } - else if (name == kOptimize) - { - if (value == kOn) mPragma.optimize = true; - else if (value == kOff) mPragma.optimize = false; - else invalidValue = true; - } - else if (name == kDebug) - { - if (value == kOn) mPragma.debug = true; - else if (value == kOff) mPragma.debug = false; - else invalidValue = true; - } - else - { - mDiagnostics.report(pp::Diagnostics::UNRECOGNIZED_PRAGMA, loc, name); - return; - } - - if (invalidValue) - mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc, - "invalid pragma value", value, - "'on' or 'off' expected"); -} - -void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc, - const std::string& name, - const std::string& behavior) -{ - static const std::string kExtAll("all"); - - TBehavior behaviorVal = getBehavior(behavior); - if (behaviorVal == EBhUndefined) - { - mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc, - "behavior", name, "invalid"); - return; - } - - if (name == kExtAll) - { - if (behaviorVal == EBhRequire) - { - mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc, - "extension", name, - "cannot have 'require' behavior"); - } - else if (behaviorVal == EBhEnable) - { - mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc, - "extension", name, - "cannot have 'enable' behavior"); - } - else - { - for (TExtensionBehavior::iterator iter = mExtensionBehavior.begin(); - iter != mExtensionBehavior.end(); ++iter) - iter->second = behaviorVal; - } - return; - } - - TExtensionBehavior::iterator iter = mExtensionBehavior.find(name); - if (iter != mExtensionBehavior.end()) - { - iter->second = behaviorVal; - return; - } - - pp::Diagnostics::Severity severity = pp::Diagnostics::ERROR; - switch (behaviorVal) { - case EBhRequire: - severity = pp::Diagnostics::ERROR; - break; - case EBhEnable: - case EBhWarn: - case EBhDisable: - severity = pp::Diagnostics::WARNING; - break; - default: - UNREACHABLE(); - break; - } - mDiagnostics.writeInfo(severity, loc, - "extension", name, "is not supported"); -} - -void TDirectiveHandler::handleVersion(const pp::SourceLocation& loc, - int version) -{ - static const int kVersion = 100; - - if (version != kVersion) - { - std::stringstream stream; - stream << version; - std::string str = stream.str(); - mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc, - "version number", str, "not supported"); - } -} diff --git a/src/3rdparty/angle/src/compiler/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/DirectiveHandler.h deleted file mode 100644 index 95ca59d6fe..0000000000 --- a/src/3rdparty/angle/src/compiler/DirectiveHandler.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_DIRECTIVE_HANDLER_H_ -#define COMPILER_DIRECTIVE_HANDLER_H_ - -#include "compiler/ExtensionBehavior.h" -#include "compiler/Pragma.h" -#include "compiler/preprocessor/DirectiveHandlerBase.h" - -class TDiagnostics; - -class TDirectiveHandler : public pp::DirectiveHandler -{ - public: - TDirectiveHandler(TExtensionBehavior& extBehavior, - TDiagnostics& diagnostics); - virtual ~TDirectiveHandler(); - - const TPragma& pragma() const { return mPragma; } - const TExtensionBehavior& extensionBehavior() const { return mExtensionBehavior; } - - virtual void handleError(const pp::SourceLocation& loc, - const std::string& msg); - - virtual void handlePragma(const pp::SourceLocation& loc, - const std::string& name, - const std::string& value); - - virtual void handleExtension(const pp::SourceLocation& loc, - const std::string& name, - const std::string& behavior); - - virtual void handleVersion(const pp::SourceLocation& loc, - int version); - - private: - TPragma mPragma; - TExtensionBehavior& mExtensionBehavior; - TDiagnostics& mDiagnostics; -}; - -#endif // COMPILER_DIRECTIVE_HANDLER_H_ diff --git a/src/3rdparty/angle/src/compiler/ExtensionBehavior.h b/src/3rdparty/angle/src/compiler/ExtensionBehavior.h deleted file mode 100644 index 5c1595fb21..0000000000 --- a/src/3rdparty/angle/src/compiler/ExtensionBehavior.h +++ /dev/null @@ -1,37 +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. -// - -#ifndef _EXTENSION_BEHAVIOR_INCLUDED_ -#define _EXTENSION_BEHAVIOR_INCLUDED_ - -#include -#include - -typedef enum -{ - EBhRequire, - EBhEnable, - EBhWarn, - EBhDisable, - EBhUndefined -} TBehavior; - -inline const char* getBehaviorString(TBehavior b) -{ - switch(b) - { - case EBhRequire: return "require"; - case EBhEnable: return "enable"; - case EBhWarn: return "warn"; - case EBhDisable: return "disable"; - default: return NULL; - } -} - -// Mapping between extension name and behavior. -typedef std::map TExtensionBehavior; - -#endif // _EXTENSION_TABLE_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/ForLoopUnroll.cpp b/src/3rdparty/angle/src/compiler/ForLoopUnroll.cpp deleted file mode 100644 index 27a13eabab..0000000000 --- a/src/3rdparty/angle/src/compiler/ForLoopUnroll.cpp +++ /dev/null @@ -1,215 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/ForLoopUnroll.h" - -namespace { - -class IntegerForLoopUnrollMarker : public TIntermTraverser { -public: - - virtual bool visitLoop(Visit, TIntermLoop* node) - { - // This is called after ValidateLimitations pass, so all the ASSERT - // should never fail. - // See ValidateLimitations::validateForLoopInit(). - ASSERT(node); - ASSERT(node->getType() == ELoopFor); - ASSERT(node->getInit()); - TIntermAggregate* decl = node->getInit()->getAsAggregate(); - ASSERT(decl && decl->getOp() == EOpDeclaration); - TIntermSequence& declSeq = decl->getSequence(); - ASSERT(declSeq.size() == 1); - TIntermBinary* declInit = declSeq[0]->getAsBinaryNode(); - ASSERT(declInit && declInit->getOp() == EOpInitialize); - ASSERT(declInit->getLeft()); - TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode(); - ASSERT(symbol); - TBasicType type = symbol->getBasicType(); - ASSERT(type == EbtInt || type == EbtFloat); - if (type == EbtInt) - node->setUnrollFlag(true); - return true; - } - -}; - -} // anonymous namepsace - -void ForLoopUnroll::FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info) -{ - ASSERT(node->getType() == ELoopFor); - ASSERT(node->getUnrollFlag()); - - TIntermNode* init = node->getInit(); - ASSERT(init != NULL); - TIntermAggregate* decl = init->getAsAggregate(); - ASSERT((decl != NULL) && (decl->getOp() == EOpDeclaration)); - TIntermSequence& declSeq = decl->getSequence(); - ASSERT(declSeq.size() == 1); - TIntermBinary* declInit = declSeq[0]->getAsBinaryNode(); - ASSERT((declInit != NULL) && (declInit->getOp() == EOpInitialize)); - TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode(); - ASSERT(symbol != NULL); - ASSERT(symbol->getBasicType() == EbtInt); - - info.id = symbol->getId(); - - ASSERT(declInit->getRight() != NULL); - TIntermConstantUnion* initNode = declInit->getRight()->getAsConstantUnion(); - ASSERT(initNode != NULL); - - info.initValue = evaluateIntConstant(initNode); - info.currentValue = info.initValue; - - TIntermNode* cond = node->getCondition(); - ASSERT(cond != NULL); - TIntermBinary* binOp = cond->getAsBinaryNode(); - ASSERT(binOp != NULL); - ASSERT(binOp->getRight() != NULL); - ASSERT(binOp->getRight()->getAsConstantUnion() != NULL); - - info.incrementValue = getLoopIncrement(node); - info.stopValue = evaluateIntConstant( - binOp->getRight()->getAsConstantUnion()); - info.op = binOp->getOp(); -} - -void ForLoopUnroll::Step() -{ - ASSERT(mLoopIndexStack.size() > 0); - TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1]; - info.currentValue += info.incrementValue; -} - -bool ForLoopUnroll::SatisfiesLoopCondition() -{ - ASSERT(mLoopIndexStack.size() > 0); - TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1]; - // Relational operator is one of: > >= < <= == or !=. - switch (info.op) { - case EOpEqual: - return (info.currentValue == info.stopValue); - case EOpNotEqual: - return (info.currentValue != info.stopValue); - case EOpLessThan: - return (info.currentValue < info.stopValue); - case EOpGreaterThan: - return (info.currentValue > info.stopValue); - case EOpLessThanEqual: - return (info.currentValue <= info.stopValue); - case EOpGreaterThanEqual: - return (info.currentValue >= info.stopValue); - default: - UNREACHABLE(); - } - return false; -} - -bool ForLoopUnroll::NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol) -{ - for (TVector::iterator i = mLoopIndexStack.begin(); - i != mLoopIndexStack.end(); - ++i) { - if (i->id == symbol->getId()) - return true; - } - return false; -} - -int ForLoopUnroll::GetLoopIndexValue(TIntermSymbol* symbol) -{ - for (TVector::iterator i = mLoopIndexStack.begin(); - i != mLoopIndexStack.end(); - ++i) { - if (i->id == symbol->getId()) - return i->currentValue; - } - UNREACHABLE(); - return false; -} - -void ForLoopUnroll::Push(TLoopIndexInfo& info) -{ - mLoopIndexStack.push_back(info); -} - -void ForLoopUnroll::Pop() -{ - mLoopIndexStack.pop_back(); -} - -// static -void ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling( - TIntermNode* root) -{ - ASSERT(root); - - IntegerForLoopUnrollMarker marker; - root->traverse(&marker); -} - -int ForLoopUnroll::getLoopIncrement(TIntermLoop* node) -{ - TIntermNode* expr = node->getExpression(); - ASSERT(expr != NULL); - // for expression has one of the following forms: - // loop_index++ - // loop_index-- - // loop_index += constant_expression - // loop_index -= constant_expression - // ++loop_index - // --loop_index - // The last two forms are not specified in the spec, but I am assuming - // its an oversight. - TIntermUnary* unOp = expr->getAsUnaryNode(); - TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode(); - - TOperator op = EOpNull; - TIntermConstantUnion* incrementNode = NULL; - if (unOp != NULL) { - op = unOp->getOp(); - } else if (binOp != NULL) { - op = binOp->getOp(); - ASSERT(binOp->getRight() != NULL); - incrementNode = binOp->getRight()->getAsConstantUnion(); - ASSERT(incrementNode != NULL); - } - - int increment = 0; - // The operator is one of: ++ -- += -=. - switch (op) { - case EOpPostIncrement: - case EOpPreIncrement: - ASSERT((unOp != NULL) && (binOp == NULL)); - increment = 1; - break; - case EOpPostDecrement: - case EOpPreDecrement: - ASSERT((unOp != NULL) && (binOp == NULL)); - increment = -1; - break; - case EOpAddAssign: - ASSERT((unOp == NULL) && (binOp != NULL)); - increment = evaluateIntConstant(incrementNode); - break; - case EOpSubAssign: - ASSERT((unOp == NULL) && (binOp != NULL)); - increment = - evaluateIntConstant(incrementNode); - break; - default: - ASSERT(false); - } - - return increment; -} - -int ForLoopUnroll::evaluateIntConstant(TIntermConstantUnion* node) -{ - ASSERT((node != NULL) && (node->getUnionArrayPointer() != NULL)); - return node->getIConst(0); -} - diff --git a/src/3rdparty/angle/src/compiler/ForLoopUnroll.h b/src/3rdparty/angle/src/compiler/ForLoopUnroll.h deleted file mode 100644 index e800e25b1f..0000000000 --- a/src/3rdparty/angle/src/compiler/ForLoopUnroll.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/intermediate.h" - -struct TLoopIndexInfo { - int id; - int initValue; - int stopValue; - int incrementValue; - TOperator op; - int currentValue; -}; - -class ForLoopUnroll { -public: - ForLoopUnroll() { } - - void FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info); - - // Update the info.currentValue for the next loop iteration. - void Step(); - - // Return false if loop condition is no longer satisfied. - bool SatisfiesLoopCondition(); - - // Check if the symbol is the index of a loop that's unrolled. - bool NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol); - - // Return the current value of a given loop index symbol. - int GetLoopIndexValue(TIntermSymbol* symbol); - - void Push(TLoopIndexInfo& info); - void Pop(); - - static void MarkForLoopsWithIntegerIndicesForUnrolling(TIntermNode* root); - -private: - int getLoopIncrement(TIntermLoop* node); - - int evaluateIntConstant(TIntermConstantUnion* node); - - TVector mLoopIndexStack; -}; - diff --git a/src/3rdparty/angle/src/compiler/HashNames.h b/src/3rdparty/angle/src/compiler/HashNames.h deleted file mode 100644 index d2141e2d85..0000000000 --- a/src/3rdparty/angle/src/compiler/HashNames.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_HASH_NAMES_H_ -#define COMPILER_HASH_NAMES_H_ - -#include - -#include "compiler/intermediate.h" -#include "GLSLANG/ShaderLang.h" - -#define HASHED_NAME_PREFIX "webgl_" - -typedef std::map NameMap; - -#endif // COMPILER_HASH_NAMES_H_ diff --git a/src/3rdparty/angle/src/compiler/InfoSink.cpp b/src/3rdparty/angle/src/compiler/InfoSink.cpp deleted file mode 100644 index d20a6c0175..0000000000 --- a/src/3rdparty/angle/src/compiler/InfoSink.cpp +++ /dev/null @@ -1,54 +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. -// - -#include "compiler/InfoSink.h" - -void TInfoSinkBase::prefix(TPrefixType p) { - switch(p) { - case EPrefixNone: - break; - case EPrefixWarning: - sink.append("WARNING: "); - break; - case EPrefixError: - sink.append("ERROR: "); - break; - case EPrefixInternalError: - sink.append("INTERNAL ERROR: "); - break; - case EPrefixUnimplemented: - sink.append("UNIMPLEMENTED: "); - break; - case EPrefixNote: - sink.append("NOTE: "); - break; - default: - sink.append("UNKOWN ERROR: "); - break; - } -} - -void TInfoSinkBase::location(int file, int line) { - TPersistStringStream stream; - if (line) - stream << file << ":" << line; - else - stream << file << ":? "; - stream << ": "; - - sink.append(stream.str()); -} - -void TInfoSinkBase::location(const TSourceLoc& loc) { - location(loc.first_file, loc.first_line); -} - -void TInfoSinkBase::message(TPrefixType p, const TSourceLoc& loc, const char* m) { - prefix(p); - location(loc); - sink.append(m); - sink.append("\n"); -} diff --git a/src/3rdparty/angle/src/compiler/InfoSink.h b/src/3rdparty/angle/src/compiler/InfoSink.h deleted file mode 100644 index 6888838142..0000000000 --- a/src/3rdparty/angle/src/compiler/InfoSink.h +++ /dev/null @@ -1,115 +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. -// - -#ifndef _INFOSINK_INCLUDED_ -#define _INFOSINK_INCLUDED_ - -#include -#include "compiler/Common.h" - -// Returns the fractional part of the given floating-point number. -inline float fractionalPart(float f) { - float intPart = 0.0f; - return modff(f, &intPart); -} - -// -// TPrefixType is used to centralize how info log messages start. -// See below. -// -enum TPrefixType { - EPrefixNone, - EPrefixWarning, - EPrefixError, - EPrefixInternalError, - EPrefixUnimplemented, - EPrefixNote -}; - -// -// Encapsulate info logs for all objects that have them. -// -// The methods are a general set of tools for getting a variety of -// messages and types inserted into the log. -// -class TInfoSinkBase { -public: - TInfoSinkBase() {} - - template - TInfoSinkBase& operator<<(const T& t) { - TPersistStringStream stream; - stream << t; - sink.append(stream.str()); - return *this; - } - // Override << operator for specific types. It is faster to append strings - // and characters directly to the sink. - TInfoSinkBase& operator<<(char c) { - sink.append(1, c); - return *this; - } - TInfoSinkBase& operator<<(const char* str) { - sink.append(str); - return *this; - } - TInfoSinkBase& operator<<(const TPersistString& str) { - sink.append(str); - return *this; - } - TInfoSinkBase& operator<<(const TString& str) { - sink.append(str.c_str()); - return *this; - } - // Make sure floats are written with correct precision. - TInfoSinkBase& operator<<(float f) { - // Make sure that at least one decimal point is written. If a number - // does not have a fractional part, the default precision format does - // not write the decimal portion which gets interpreted as integer by - // the compiler. - TPersistStringStream stream; - if (fractionalPart(f) == 0.0f) { - stream.precision(1); - stream << std::showpoint << std::fixed << f; - } else { - stream.unsetf(std::ios::fixed); - stream.unsetf(std::ios::scientific); - stream.precision(8); - stream << f; - } - sink.append(stream.str()); - return *this; - } - // Write boolean values as their names instead of integral value. - TInfoSinkBase& operator<<(bool b) { - const char* str = b ? "true" : "false"; - sink.append(str); - return *this; - } - - void erase() { sink.clear(); } - int size() { return static_cast(sink.size()); } - - const TPersistString& str() const { return sink; } - const char* c_str() const { return sink.c_str(); } - - void prefix(TPrefixType p); - void location(int file, int line); - void location(const TSourceLoc& loc); - void message(TPrefixType p, const TSourceLoc& loc, const char* m); - -private: - TPersistString sink; -}; - -class TInfoSink { -public: - TInfoSinkBase info; - TInfoSinkBase debug; - TInfoSinkBase obj; -}; - -#endif // _INFOSINK_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/Initialize.cpp b/src/3rdparty/angle/src/compiler/Initialize.cpp deleted file mode 100644 index 236383d874..0000000000 --- a/src/3rdparty/angle/src/compiler/Initialize.cpp +++ /dev/null @@ -1,564 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// Create strings that declare built-in definitions, add built-ins that -// cannot be expressed in the files, and establish mappings between -// built-in functions and operators. -// - -#include "compiler/Initialize.h" - -#include "compiler/intermediate.h" - -void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable) -{ - TType *float1 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 1); - TType *float2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2); - TType *float3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3); - TType *float4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4); - - TType *int2 = new TType(EbtInt, EbpUndefined, EvqGlobal, 2); - TType *int3 = new TType(EbtInt, EbpUndefined, EvqGlobal, 3); - TType *int4 = new TType(EbtInt, EbpUndefined, EvqGlobal, 4); - - // - // Angle and Trigonometric Functions. - // - symbolTable.insertBuiltIn(float1, "radians", float1); - symbolTable.insertBuiltIn(float2, "radians", float2); - symbolTable.insertBuiltIn(float3, "radians", float3); - symbolTable.insertBuiltIn(float4, "radians", float4); - - symbolTable.insertBuiltIn(float1, "degrees", float1); - symbolTable.insertBuiltIn(float2, "degrees", float2); - symbolTable.insertBuiltIn(float3, "degrees", float3); - symbolTable.insertBuiltIn(float4, "degrees", float4); - - symbolTable.insertBuiltIn(float1, "sin", float1); - symbolTable.insertBuiltIn(float2, "sin", float2); - symbolTable.insertBuiltIn(float3, "sin", float3); - symbolTable.insertBuiltIn(float4, "sin", float4); - - symbolTable.insertBuiltIn(float1, "cos", float1); - symbolTable.insertBuiltIn(float2, "cos", float2); - symbolTable.insertBuiltIn(float3, "cos", float3); - symbolTable.insertBuiltIn(float4, "cos", float4); - - symbolTable.insertBuiltIn(float1, "tan", float1); - symbolTable.insertBuiltIn(float2, "tan", float2); - symbolTable.insertBuiltIn(float3, "tan", float3); - symbolTable.insertBuiltIn(float4, "tan", float4); - - symbolTable.insertBuiltIn(float1, "asin", float1); - symbolTable.insertBuiltIn(float2, "asin", float2); - symbolTable.insertBuiltIn(float3, "asin", float3); - symbolTable.insertBuiltIn(float4, "asin", float4); - - symbolTable.insertBuiltIn(float1, "acos", float1); - symbolTable.insertBuiltIn(float2, "acos", float2); - symbolTable.insertBuiltIn(float3, "acos", float3); - symbolTable.insertBuiltIn(float4, "acos", float4); - - symbolTable.insertBuiltIn(float1, "atan", float1, float1); - symbolTable.insertBuiltIn(float2, "atan", float2, float2); - symbolTable.insertBuiltIn(float3, "atan", float3, float3); - symbolTable.insertBuiltIn(float4, "atan", float4, float4); - - symbolTable.insertBuiltIn(float1, "atan", float1); - symbolTable.insertBuiltIn(float2, "atan", float2); - symbolTable.insertBuiltIn(float3, "atan", float3); - symbolTable.insertBuiltIn(float4, "atan", float4); - - // - // Exponential Functions. - // - symbolTable.insertBuiltIn(float1, "pow", float1, float1); - symbolTable.insertBuiltIn(float2, "pow", float2, float2); - symbolTable.insertBuiltIn(float3, "pow", float3, float3); - symbolTable.insertBuiltIn(float4, "pow", float4, float4); - - symbolTable.insertBuiltIn(float1, "exp", float1); - symbolTable.insertBuiltIn(float2, "exp", float2); - symbolTable.insertBuiltIn(float3, "exp", float3); - symbolTable.insertBuiltIn(float4, "exp", float4); - - symbolTable.insertBuiltIn(float1, "log", float1); - symbolTable.insertBuiltIn(float2, "log", float2); - symbolTable.insertBuiltIn(float3, "log", float3); - symbolTable.insertBuiltIn(float4, "log", float4); - - symbolTable.insertBuiltIn(float1, "exp2", float1); - symbolTable.insertBuiltIn(float2, "exp2", float2); - symbolTable.insertBuiltIn(float3, "exp2", float3); - symbolTable.insertBuiltIn(float4, "exp2", float4); - - symbolTable.insertBuiltIn(float1, "log2", float1); - symbolTable.insertBuiltIn(float2, "log2", float2); - symbolTable.insertBuiltIn(float3, "log2", float3); - symbolTable.insertBuiltIn(float4, "log2", float4); - - symbolTable.insertBuiltIn(float1, "sqrt", float1); - symbolTable.insertBuiltIn(float2, "sqrt", float2); - symbolTable.insertBuiltIn(float3, "sqrt", float3); - symbolTable.insertBuiltIn(float4, "sqrt", float4); - - symbolTable.insertBuiltIn(float1, "inversesqrt", float1); - symbolTable.insertBuiltIn(float2, "inversesqrt", float2); - symbolTable.insertBuiltIn(float3, "inversesqrt", float3); - symbolTable.insertBuiltIn(float4, "inversesqrt", float4); - - // - // Common Functions. - // - symbolTable.insertBuiltIn(float1, "abs", float1); - symbolTable.insertBuiltIn(float2, "abs", float2); - symbolTable.insertBuiltIn(float3, "abs", float3); - symbolTable.insertBuiltIn(float4, "abs", float4); - - symbolTable.insertBuiltIn(float1, "sign", float1); - symbolTable.insertBuiltIn(float2, "sign", float2); - symbolTable.insertBuiltIn(float3, "sign", float3); - symbolTable.insertBuiltIn(float4, "sign", float4); - - symbolTable.insertBuiltIn(float1, "floor", float1); - symbolTable.insertBuiltIn(float2, "floor", float2); - symbolTable.insertBuiltIn(float3, "floor", float3); - symbolTable.insertBuiltIn(float4, "floor", float4); - - symbolTable.insertBuiltIn(float1, "ceil", float1); - symbolTable.insertBuiltIn(float2, "ceil", float2); - symbolTable.insertBuiltIn(float3, "ceil", float3); - symbolTable.insertBuiltIn(float4, "ceil", float4); - - symbolTable.insertBuiltIn(float1, "fract", float1); - symbolTable.insertBuiltIn(float2, "fract", float2); - symbolTable.insertBuiltIn(float3, "fract", float3); - symbolTable.insertBuiltIn(float4, "fract", float4); - - symbolTable.insertBuiltIn(float1, "mod", float1, float1); - symbolTable.insertBuiltIn(float2, "mod", float2, float1); - symbolTable.insertBuiltIn(float3, "mod", float3, float1); - symbolTable.insertBuiltIn(float4, "mod", float4, float1); - symbolTable.insertBuiltIn(float2, "mod", float2, float2); - symbolTable.insertBuiltIn(float3, "mod", float3, float3); - symbolTable.insertBuiltIn(float4, "mod", float4, float4); - - symbolTable.insertBuiltIn(float1, "min", float1, float1); - symbolTable.insertBuiltIn(float2, "min", float2, float1); - symbolTable.insertBuiltIn(float3, "min", float3, float1); - symbolTable.insertBuiltIn(float4, "min", float4, float1); - symbolTable.insertBuiltIn(float2, "min", float2, float2); - symbolTable.insertBuiltIn(float3, "min", float3, float3); - symbolTable.insertBuiltIn(float4, "min", float4, float4); - - symbolTable.insertBuiltIn(float1, "max", float1, float1); - symbolTable.insertBuiltIn(float2, "max", float2, float1); - symbolTable.insertBuiltIn(float3, "max", float3, float1); - symbolTable.insertBuiltIn(float4, "max", float4, float1); - symbolTable.insertBuiltIn(float2, "max", float2, float2); - symbolTable.insertBuiltIn(float3, "max", float3, float3); - symbolTable.insertBuiltIn(float4, "max", float4, float4); - - symbolTable.insertBuiltIn(float1, "clamp", float1, float1, float1); - symbolTable.insertBuiltIn(float2, "clamp", float2, float1, float1); - symbolTable.insertBuiltIn(float3, "clamp", float3, float1, float1); - symbolTable.insertBuiltIn(float4, "clamp", float4, float1, float1); - symbolTable.insertBuiltIn(float2, "clamp", float2, float2, float2); - symbolTable.insertBuiltIn(float3, "clamp", float3, float3, float3); - symbolTable.insertBuiltIn(float4, "clamp", float4, float4, float4); - - symbolTable.insertBuiltIn(float1, "mix", float1, float1, float1); - symbolTable.insertBuiltIn(float2, "mix", float2, float2, float1); - symbolTable.insertBuiltIn(float3, "mix", float3, float3, float1); - symbolTable.insertBuiltIn(float4, "mix", float4, float4, float1); - symbolTable.insertBuiltIn(float2, "mix", float2, float2, float2); - symbolTable.insertBuiltIn(float3, "mix", float3, float3, float3); - symbolTable.insertBuiltIn(float4, "mix", float4, float4, float4); - - symbolTable.insertBuiltIn(float1, "step", float1, float1); - symbolTable.insertBuiltIn(float2, "step", float2, float2); - symbolTable.insertBuiltIn(float3, "step", float3, float3); - symbolTable.insertBuiltIn(float4, "step", float4, float4); - symbolTable.insertBuiltIn(float2, "step", float1, float2); - symbolTable.insertBuiltIn(float3, "step", float1, float3); - symbolTable.insertBuiltIn(float4, "step", float1, float4); - - symbolTable.insertBuiltIn(float1, "smoothstep", float1, float1, float1); - symbolTable.insertBuiltIn(float2, "smoothstep", float2, float2, float2); - symbolTable.insertBuiltIn(float3, "smoothstep", float3, float3, float3); - symbolTable.insertBuiltIn(float4, "smoothstep", float4, float4, float4); - symbolTable.insertBuiltIn(float2, "smoothstep", float1, float1, float2); - symbolTable.insertBuiltIn(float3, "smoothstep", float1, float1, float3); - symbolTable.insertBuiltIn(float4, "smoothstep", float1, float1, float4); - - // - // Geometric Functions. - // - symbolTable.insertBuiltIn(float1, "length", float1); - symbolTable.insertBuiltIn(float1, "length", float2); - symbolTable.insertBuiltIn(float1, "length", float3); - symbolTable.insertBuiltIn(float1, "length", float4); - - symbolTable.insertBuiltIn(float1, "distance", float1, float1); - symbolTable.insertBuiltIn(float1, "distance", float2, float2); - symbolTable.insertBuiltIn(float1, "distance", float3, float3); - symbolTable.insertBuiltIn(float1, "distance", float4, float4); - - symbolTable.insertBuiltIn(float1, "dot", float1, float1); - symbolTable.insertBuiltIn(float1, "dot", float2, float2); - symbolTable.insertBuiltIn(float1, "dot", float3, float3); - symbolTable.insertBuiltIn(float1, "dot", float4, float4); - - symbolTable.insertBuiltIn(float3, "cross", float3, float3); - symbolTable.insertBuiltIn(float1, "normalize", float1); - symbolTable.insertBuiltIn(float2, "normalize", float2); - symbolTable.insertBuiltIn(float3, "normalize", float3); - symbolTable.insertBuiltIn(float4, "normalize", float4); - - symbolTable.insertBuiltIn(float1, "faceforward", float1, float1, float1); - symbolTable.insertBuiltIn(float2, "faceforward", float2, float2, float2); - symbolTable.insertBuiltIn(float3, "faceforward", float3, float3, float3); - symbolTable.insertBuiltIn(float4, "faceforward", float4, float4, float4); - - symbolTable.insertBuiltIn(float1, "reflect", float1, float1); - symbolTable.insertBuiltIn(float2, "reflect", float2, float2); - symbolTable.insertBuiltIn(float3, "reflect", float3, float3); - symbolTable.insertBuiltIn(float4, "reflect", float4, float4); - - symbolTable.insertBuiltIn(float1, "refract", float1, float1, float1); - symbolTable.insertBuiltIn(float2, "refract", float2, float2, float1); - symbolTable.insertBuiltIn(float3, "refract", float3, float3, float1); - symbolTable.insertBuiltIn(float4, "refract", float4, float4, float1); - - TType *mat2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2, true); - TType *mat3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3, true); - TType *mat4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4, true); - - // - // Matrix Functions. - // - symbolTable.insertBuiltIn(mat2, "matrixCompMult", mat2, mat2); - symbolTable.insertBuiltIn(mat3, "matrixCompMult", mat3, mat3); - symbolTable.insertBuiltIn(mat4, "matrixCompMult", mat4, mat4); - - TType *bool1 = new TType(EbtBool, EbpUndefined, EvqGlobal, 1); - TType *bool2 = new TType(EbtBool, EbpUndefined, EvqGlobal, 2); - TType *bool3 = new TType(EbtBool, EbpUndefined, EvqGlobal, 3); - TType *bool4 = new TType(EbtBool, EbpUndefined, EvqGlobal, 4); - - // - // Vector relational functions. - // - symbolTable.insertBuiltIn(bool2, "lessThan", float2, float2); - symbolTable.insertBuiltIn(bool3, "lessThan", float3, float3); - symbolTable.insertBuiltIn(bool4, "lessThan", float4, float4); - - symbolTable.insertBuiltIn(bool2, "lessThan", int2, int2); - symbolTable.insertBuiltIn(bool3, "lessThan", int3, int3); - symbolTable.insertBuiltIn(bool4, "lessThan", int4, int4); - - symbolTable.insertBuiltIn(bool2, "lessThanEqual", float2, float2); - symbolTable.insertBuiltIn(bool3, "lessThanEqual", float3, float3); - symbolTable.insertBuiltIn(bool4, "lessThanEqual", float4, float4); - - symbolTable.insertBuiltIn(bool2, "lessThanEqual", int2, int2); - symbolTable.insertBuiltIn(bool3, "lessThanEqual", int3, int3); - symbolTable.insertBuiltIn(bool4, "lessThanEqual", int4, int4); - - symbolTable.insertBuiltIn(bool2, "greaterThan", float2, float2); - symbolTable.insertBuiltIn(bool3, "greaterThan", float3, float3); - symbolTable.insertBuiltIn(bool4, "greaterThan", float4, float4); - - symbolTable.insertBuiltIn(bool2, "greaterThan", int2, int2); - symbolTable.insertBuiltIn(bool3, "greaterThan", int3, int3); - symbolTable.insertBuiltIn(bool4, "greaterThan", int4, int4); - - symbolTable.insertBuiltIn(bool2, "greaterThanEqual", float2, float2); - symbolTable.insertBuiltIn(bool3, "greaterThanEqual", float3, float3); - symbolTable.insertBuiltIn(bool4, "greaterThanEqual", float4, float4); - - symbolTable.insertBuiltIn(bool2, "greaterThanEqual", int2, int2); - symbolTable.insertBuiltIn(bool3, "greaterThanEqual", int3, int3); - symbolTable.insertBuiltIn(bool4, "greaterThanEqual", int4, int4); - - symbolTable.insertBuiltIn(bool2, "equal", float2, float2); - symbolTable.insertBuiltIn(bool3, "equal", float3, float3); - symbolTable.insertBuiltIn(bool4, "equal", float4, float4); - - symbolTable.insertBuiltIn(bool2, "equal", int2, int2); - symbolTable.insertBuiltIn(bool3, "equal", int3, int3); - symbolTable.insertBuiltIn(bool4, "equal", int4, int4); - - symbolTable.insertBuiltIn(bool2, "equal", bool2, bool2); - symbolTable.insertBuiltIn(bool3, "equal", bool3, bool3); - symbolTable.insertBuiltIn(bool4, "equal", bool4, bool4); - - symbolTable.insertBuiltIn(bool2, "notEqual", float2, float2); - symbolTable.insertBuiltIn(bool3, "notEqual", float3, float3); - symbolTable.insertBuiltIn(bool4, "notEqual", float4, float4); - - symbolTable.insertBuiltIn(bool2, "notEqual", int2, int2); - symbolTable.insertBuiltIn(bool3, "notEqual", int3, int3); - symbolTable.insertBuiltIn(bool4, "notEqual", int4, int4); - - symbolTable.insertBuiltIn(bool2, "notEqual", bool2, bool2); - symbolTable.insertBuiltIn(bool3, "notEqual", bool3, bool3); - symbolTable.insertBuiltIn(bool4, "notEqual", bool4, bool4); - - symbolTable.insertBuiltIn(bool1, "any", bool2); - symbolTable.insertBuiltIn(bool1, "any", bool3); - symbolTable.insertBuiltIn(bool1, "any", bool4); - - symbolTable.insertBuiltIn(bool1, "all", bool2); - symbolTable.insertBuiltIn(bool1, "all", bool3); - symbolTable.insertBuiltIn(bool1, "all", bool4); - - symbolTable.insertBuiltIn(bool2, "not", bool2); - symbolTable.insertBuiltIn(bool3, "not", bool3); - symbolTable.insertBuiltIn(bool4, "not", bool4); - - TType *sampler2D = new TType(EbtSampler2D, EbpUndefined, EvqGlobal, 1); - TType *samplerCube = new TType(EbtSamplerCube, EbpUndefined, EvqGlobal, 1); - - // - // Texture Functions for GLSL ES 1.0 - // - symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2); - symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3); - symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4); - symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3); - - if (resources.OES_EGL_image_external) - { - TType *samplerExternalOES = new TType(EbtSamplerExternalOES, EbpUndefined, EvqGlobal, 1); - - symbolTable.insertBuiltIn(float4, "texture2D", samplerExternalOES, float2); - symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float3); - symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float4); - } - - if (resources.ARB_texture_rectangle) - { - TType *sampler2DRect = new TType(EbtSampler2DRect, EbpUndefined, EvqGlobal, 1); - - symbolTable.insertBuiltIn(float4, "texture2DRect", sampler2DRect, float2); - symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float3); - symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float4); - } - - if (type == SH_FRAGMENT_SHADER) - { - symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2, float1); - symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3, float1); - symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4, float1); - symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3, float1); - - if (resources.OES_standard_derivatives) - { - symbolTable.insertBuiltIn(float1, "dFdx", float1); - symbolTable.insertBuiltIn(float2, "dFdx", float2); - symbolTable.insertBuiltIn(float3, "dFdx", float3); - symbolTable.insertBuiltIn(float4, "dFdx", float4); - - symbolTable.insertBuiltIn(float1, "dFdy", float1); - symbolTable.insertBuiltIn(float2, "dFdy", float2); - symbolTable.insertBuiltIn(float3, "dFdy", float3); - symbolTable.insertBuiltIn(float4, "dFdy", float4); - - symbolTable.insertBuiltIn(float1, "fwidth", float1); - symbolTable.insertBuiltIn(float2, "fwidth", float2); - symbolTable.insertBuiltIn(float3, "fwidth", float3); - symbolTable.insertBuiltIn(float4, "fwidth", float4); - } - } - - if(type == SH_VERTEX_SHADER) - { - symbolTable.insertBuiltIn(float4, "texture2DLod", sampler2D, float2, float1); - symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float3, float1); - symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float4, float1); - symbolTable.insertBuiltIn(float4, "textureCubeLod", samplerCube, float3, float1); - } - - // - // Depth range in window coordinates - // - TFieldList *fields = NewPoolTFieldList(); - TField *near = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("near")); - TField *far = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("far")); - TField *diff = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("diff")); - fields->push_back(near); - fields->push_back(far); - fields->push_back(diff); - TStructure *depthRangeStruct = new TStructure(NewPoolTString("gl_DepthRangeParameters"), fields); - TVariable *depthRangeParameters = new TVariable(&depthRangeStruct->name(), depthRangeStruct, true); - symbolTable.insert(*depthRangeParameters); - TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(depthRangeStruct)); - depthRange->setQualifier(EvqUniform); - symbolTable.insert(*depthRange); - - // - // Implementation dependent built-in constants. - // - symbolTable.insertConstInt("gl_MaxVertexAttribs", resources.MaxVertexAttribs); - symbolTable.insertConstInt("gl_MaxVertexUniformVectors", resources.MaxVertexUniformVectors); - symbolTable.insertConstInt("gl_MaxVaryingVectors", resources.MaxVaryingVectors); - symbolTable.insertConstInt("gl_MaxVertexTextureImageUnits", resources.MaxVertexTextureImageUnits); - symbolTable.insertConstInt("gl_MaxCombinedTextureImageUnits", resources.MaxCombinedTextureImageUnits); - symbolTable.insertConstInt("gl_MaxTextureImageUnits", resources.MaxTextureImageUnits); - symbolTable.insertConstInt("gl_MaxFragmentUniformVectors", resources.MaxFragmentUniformVectors); - - if (spec != SH_CSS_SHADERS_SPEC) - { - symbolTable.insertConstInt("gl_MaxDrawBuffers", resources.MaxDrawBuffers); - } -} - -void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, - const ShBuiltInResources &resources, - TSymbolTable &symbolTable) -{ - // - // First, insert some special built-in variables that are not in - // the built-in header files. - // - switch(type) { - case SH_FRAGMENT_SHADER: - symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4))); - symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1))); - symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2))); - - // - // In CSS Shaders, gl_FragColor, gl_FragData, and gl_MaxDrawBuffers are not available. - // Instead, css_MixColor and css_ColorMatrix are available. - // - if (spec != SH_CSS_SHADERS_SPEC) { - symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4))); - symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4))); - if (resources.EXT_frag_depth) { - symbolTable.insert(*new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1))); - symbolTable.relateToExtension("gl_FragDepthEXT", "GL_EXT_frag_depth"); - } - } else { - symbolTable.insert(*new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4))); - symbolTable.insert(*new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, true))); - } - - break; - - case SH_VERTEX_SHADER: - symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4))); - symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EbpMedium, EvqPointSize, 1))); - break; - - default: assert(false && "Language not supported"); - } - - // - // Next, identify which built-ins from the already loaded headers have - // a mapping to an operator. Those that are not identified as such are - // expected to be resolved through a library of functions, versus as - // operations. - // - symbolTable.relateToOperator("matrixCompMult", EOpMul); - - symbolTable.relateToOperator("equal", EOpVectorEqual); - symbolTable.relateToOperator("notEqual", EOpVectorNotEqual); - symbolTable.relateToOperator("lessThan", EOpLessThan); - symbolTable.relateToOperator("greaterThan", EOpGreaterThan); - symbolTable.relateToOperator("lessThanEqual", EOpLessThanEqual); - symbolTable.relateToOperator("greaterThanEqual", EOpGreaterThanEqual); - - symbolTable.relateToOperator("radians", EOpRadians); - symbolTable.relateToOperator("degrees", EOpDegrees); - symbolTable.relateToOperator("sin", EOpSin); - symbolTable.relateToOperator("cos", EOpCos); - symbolTable.relateToOperator("tan", EOpTan); - symbolTable.relateToOperator("asin", EOpAsin); - symbolTable.relateToOperator("acos", EOpAcos); - symbolTable.relateToOperator("atan", EOpAtan); - - symbolTable.relateToOperator("pow", EOpPow); - symbolTable.relateToOperator("exp2", EOpExp2); - symbolTable.relateToOperator("log", EOpLog); - symbolTable.relateToOperator("exp", EOpExp); - symbolTable.relateToOperator("log2", EOpLog2); - symbolTable.relateToOperator("sqrt", EOpSqrt); - symbolTable.relateToOperator("inversesqrt", EOpInverseSqrt); - - symbolTable.relateToOperator("abs", EOpAbs); - symbolTable.relateToOperator("sign", EOpSign); - symbolTable.relateToOperator("floor", EOpFloor); - symbolTable.relateToOperator("ceil", EOpCeil); - symbolTable.relateToOperator("fract", EOpFract); - symbolTable.relateToOperator("mod", EOpMod); - symbolTable.relateToOperator("min", EOpMin); - symbolTable.relateToOperator("max", EOpMax); - symbolTable.relateToOperator("clamp", EOpClamp); - symbolTable.relateToOperator("mix", EOpMix); - symbolTable.relateToOperator("step", EOpStep); - symbolTable.relateToOperator("smoothstep", EOpSmoothStep); - - symbolTable.relateToOperator("length", EOpLength); - symbolTable.relateToOperator("distance", EOpDistance); - symbolTable.relateToOperator("dot", EOpDot); - symbolTable.relateToOperator("cross", EOpCross); - symbolTable.relateToOperator("normalize", EOpNormalize); - symbolTable.relateToOperator("faceforward", EOpFaceForward); - symbolTable.relateToOperator("reflect", EOpReflect); - symbolTable.relateToOperator("refract", EOpRefract); - - symbolTable.relateToOperator("any", EOpAny); - symbolTable.relateToOperator("all", EOpAll); - symbolTable.relateToOperator("not", EOpVectorLogicalNot); - - // Map language-specific operators. - switch(type) { - case SH_VERTEX_SHADER: - break; - case SH_FRAGMENT_SHADER: - if (resources.OES_standard_derivatives) { - symbolTable.relateToOperator("dFdx", EOpDFdx); - symbolTable.relateToOperator("dFdy", EOpDFdy); - symbolTable.relateToOperator("fwidth", EOpFwidth); - - symbolTable.relateToExtension("dFdx", "GL_OES_standard_derivatives"); - symbolTable.relateToExtension("dFdy", "GL_OES_standard_derivatives"); - symbolTable.relateToExtension("fwidth", "GL_OES_standard_derivatives"); - } - break; - default: break; - } - - // Finally add resource-specific variables. - switch(type) { - case SH_FRAGMENT_SHADER: - if (spec != SH_CSS_SHADERS_SPEC) { - // Set up gl_FragData. The array size. - TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, false, true); - fragData.setArraySize(resources.MaxDrawBuffers); - symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData)); - } - break; - default: break; - } -} - -void InitExtensionBehavior(const ShBuiltInResources& resources, - TExtensionBehavior& extBehavior) -{ - if (resources.OES_standard_derivatives) - extBehavior["GL_OES_standard_derivatives"] = EBhUndefined; - if (resources.OES_EGL_image_external) - extBehavior["GL_OES_EGL_image_external"] = EBhUndefined; - if (resources.ARB_texture_rectangle) - extBehavior["GL_ARB_texture_rectangle"] = EBhUndefined; - if (resources.EXT_draw_buffers) - extBehavior["GL_EXT_draw_buffers"] = EBhUndefined; - if (resources.EXT_frag_depth) - extBehavior["GL_EXT_frag_depth"] = EBhUndefined; -} diff --git a/src/3rdparty/angle/src/compiler/Initialize.h b/src/3rdparty/angle/src/compiler/Initialize.h deleted file mode 100644 index 4aa13466ac..0000000000 --- a/src/3rdparty/angle/src/compiler/Initialize.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef _INITIALIZE_INCLUDED_ -#define _INITIALIZE_INCLUDED_ - -#include "compiler/Common.h" -#include "compiler/ShHandle.h" -#include "compiler/SymbolTable.h" - -void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table); - -void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, - const ShBuiltInResources& resources, - TSymbolTable& symbolTable); - -void InitExtensionBehavior(const ShBuiltInResources& resources, - TExtensionBehavior& extensionBehavior); - -#endif // _INITIALIZE_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/InitializeDll.cpp b/src/3rdparty/angle/src/compiler/InitializeDll.cpp deleted file mode 100644 index 6c7f27fced..0000000000 --- a/src/3rdparty/angle/src/compiler/InitializeDll.cpp +++ /dev/null @@ -1,32 +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. -// - -#include "compiler/InitializeDll.h" - -#include "compiler/InitializeGlobals.h" -#include "compiler/InitializeParseContext.h" -#include "compiler/osinclude.h" - -bool InitProcess() -{ - if (!InitializePoolIndex()) { - assert(0 && "InitProcess(): Failed to initalize global pool"); - return false; - } - - if (!InitializeParseContextIndex()) { - assert(0 && "InitProcess(): Failed to initalize parse context"); - return false; - } - - return true; -} - -void DetachProcess() -{ - FreeParseContextIndex(); - FreePoolIndex(); -} diff --git a/src/3rdparty/angle/src/compiler/InitializeDll.h b/src/3rdparty/angle/src/compiler/InitializeDll.h deleted file mode 100644 index 43070cc3ff..0000000000 --- a/src/3rdparty/angle/src/compiler/InitializeDll.h +++ /dev/null @@ -1,13 +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. -// -#ifndef __INITIALIZEDLL_H -#define __INITIALIZEDLL_H - -bool InitProcess(); -void DetachProcess(); - -#endif // __INITIALIZEDLL_H - diff --git a/src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp b/src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp deleted file mode 100644 index e0193e39d2..0000000000 --- a/src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/InitializeGLPosition.h" -#include "compiler/debug.h" - -bool InitializeGLPosition::visitAggregate(Visit visit, TIntermAggregate* node) -{ - bool visitChildren = !mCodeInserted; - switch (node->getOp()) - { - case EOpSequence: break; - case EOpFunction: - { - // Function definition. - ASSERT(visit == PreVisit); - if (node->getName() == "main(") - { - TIntermSequence &sequence = node->getSequence(); - ASSERT((sequence.size() == 1) || (sequence.size() == 2)); - TIntermAggregate *body = NULL; - if (sequence.size() == 1) - { - body = new TIntermAggregate(EOpSequence); - sequence.push_back(body); - } - else - { - body = sequence[1]->getAsAggregate(); - } - ASSERT(body); - insertCode(body->getSequence()); - mCodeInserted = true; - } - break; - } - default: visitChildren = false; break; - } - return visitChildren; -} - -void InitializeGLPosition::insertCode(TIntermSequence& sequence) -{ - TIntermBinary *binary = new TIntermBinary(EOpAssign); - sequence.insert(sequence.begin(), binary); - - TIntermSymbol *left = new TIntermSymbol( - 0, "gl_Position", TType(EbtFloat, EbpUndefined, EvqPosition, 4)); - binary->setLeft(left); - - ConstantUnion *u = new ConstantUnion[4]; - for (int ii = 0; ii < 3; ++ii) - u[ii].setFConst(0.0f); - u[3].setFConst(1.0f); - TIntermConstantUnion *right = new TIntermConstantUnion( - u, TType(EbtFloat, EbpUndefined, EvqConst, 4)); - binary->setRight(right); -} diff --git a/src/3rdparty/angle/src/compiler/InitializeGLPosition.h b/src/3rdparty/angle/src/compiler/InitializeGLPosition.h deleted file mode 100644 index 1b11075a13..0000000000 --- a/src/3rdparty/angle/src/compiler/InitializeGLPosition.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_INITIALIZE_GL_POSITION_H_ -#define COMPILER_INITIALIZE_GL_POSITION_H_ - -#include "compiler/intermediate.h" - -class InitializeGLPosition : public TIntermTraverser -{ -public: - InitializeGLPosition() : mCodeInserted(false) { } - -protected: - virtual bool visitBinary(Visit visit, TIntermBinary* node) { return false; } - virtual bool visitUnary(Visit visit, TIntermUnary* node) { return false; } - virtual bool visitSelection(Visit visit, TIntermSelection* node) { return false; } - virtual bool visitLoop(Visit visit, TIntermLoop* node) { return false; } - virtual bool visitBranch(Visit visit, TIntermBranch* node) { return false; } - - virtual bool visitAggregate(Visit visit, TIntermAggregate* node); - -private: - // Insert AST node in the beginning of main() for "gl_Position = vec4(0.0, 0.0, 0.0, 1.0);". - void insertCode(TIntermSequence& sequence); - - bool mCodeInserted; -}; - -#endif // COMPILER_INITIALIZE_GL_POSITION_H_ diff --git a/src/3rdparty/angle/src/compiler/InitializeGlobals.h b/src/3rdparty/angle/src/compiler/InitializeGlobals.h deleted file mode 100644 index 0715941424..0000000000 --- a/src/3rdparty/angle/src/compiler/InitializeGlobals.h +++ /dev/null @@ -1,13 +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. -// - -#ifndef __INITIALIZE_GLOBALS_INCLUDED_ -#define __INITIALIZE_GLOBALS_INCLUDED_ - -bool InitializePoolIndex(); -void FreePoolIndex(); - -#endif // __INITIALIZE_GLOBALS_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp b/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp deleted file mode 100644 index dfab027330..0000000000 --- a/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/InitializeParseContext.h" - -#include "compiler/osinclude.h" - -OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX; - -bool InitializeParseContextIndex() -{ - assert(GlobalParseContextIndex == OS_INVALID_TLS_INDEX); - - GlobalParseContextIndex = OS_AllocTLSIndex(); - return GlobalParseContextIndex != OS_INVALID_TLS_INDEX; -} - -void FreeParseContextIndex() -{ - assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); - - OS_FreeTLSIndex(GlobalParseContextIndex); - GlobalParseContextIndex = OS_INVALID_TLS_INDEX; -} - -void SetGlobalParseContext(TParseContext* context) -{ - assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); - OS_SetTLSValue(GlobalParseContextIndex, context); -} - -TParseContext* GetGlobalParseContext() -{ - assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); - return static_cast(OS_GetTLSValue(GlobalParseContextIndex)); -} - diff --git a/src/3rdparty/angle/src/compiler/InitializeParseContext.h b/src/3rdparty/angle/src/compiler/InitializeParseContext.h deleted file mode 100644 index bffbab87d0..0000000000 --- a/src/3rdparty/angle/src/compiler/InitializeParseContext.h +++ /dev/null @@ -1,17 +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. -// - -#ifndef __INITIALIZE_PARSE_CONTEXT_INCLUDED_ -#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_ - -bool InitializeParseContextIndex(); -void FreeParseContextIndex(); - -struct TParseContext; -extern void SetGlobalParseContext(TParseContext* context); -extern TParseContext* GetGlobalParseContext(); - -#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/IntermTraverse.cpp b/src/3rdparty/angle/src/compiler/IntermTraverse.cpp deleted file mode 100644 index a13877f18f..0000000000 --- a/src/3rdparty/angle/src/compiler/IntermTraverse.cpp +++ /dev/null @@ -1,293 +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. -// - -#include "compiler/intermediate.h" - -// -// Traverse the intermediate representation tree, and -// call a node type specific function for each node. -// Done recursively through the member function Traverse(). -// Node types can be skipped if their function to call is 0, -// but their subtree will still be traversed. -// Nodes with children can have their whole subtree skipped -// if preVisit is turned on and the type specific function -// returns false. -// -// preVisit, postVisit, and rightToLeft control what order -// nodes are visited in. -// - -// -// Traversal functions for terminals are straighforward.... -// -void TIntermSymbol::traverse(TIntermTraverser* it) -{ - it->visitSymbol(this); -} - -void TIntermConstantUnion::traverse(TIntermTraverser* it) -{ - it->visitConstantUnion(this); -} - -// -// Traverse a binary node. -// -void TIntermBinary::traverse(TIntermTraverser* it) -{ - bool visit = true; - - // - // visit the node before children if pre-visiting. - // - if(it->preVisit) - { - visit = it->visitBinary(PreVisit, this); - } - - // - // Visit the children, in the right order. - // - if(visit) - { - it->incrementDepth(); - - if(it->rightToLeft) - { - if(right) - { - right->traverse(it); - } - - if(it->inVisit) - { - visit = it->visitBinary(InVisit, this); - } - - if(visit && left) - { - left->traverse(it); - } - } - else - { - if(left) - { - left->traverse(it); - } - - if(it->inVisit) - { - visit = it->visitBinary(InVisit, this); - } - - if(visit && right) - { - right->traverse(it); - } - } - - it->decrementDepth(); - } - - // - // Visit the node after the children, if requested and the traversal - // hasn't been cancelled yet. - // - if(visit && it->postVisit) - { - it->visitBinary(PostVisit, this); - } -} - -// -// Traverse a unary node. Same comments in binary node apply here. -// -void TIntermUnary::traverse(TIntermTraverser* it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitUnary(PreVisit, this); - - if (visit) { - it->incrementDepth(); - operand->traverse(it); - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitUnary(PostVisit, this); -} - -// -// Traverse an aggregate node. Same comments in binary node apply here. -// -void TIntermAggregate::traverse(TIntermTraverser* it) -{ - bool visit = true; - - if(it->preVisit) - { - visit = it->visitAggregate(PreVisit, this); - } - - if(visit) - { - it->incrementDepth(); - - if(it->rightToLeft) - { - for(TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++) - { - (*sit)->traverse(it); - - if(visit && it->inVisit) - { - if(*sit != sequence.front()) - { - visit = it->visitAggregate(InVisit, this); - } - } - } - } - else - { - for(TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) - { - (*sit)->traverse(it); - - if(visit && it->inVisit) - { - if(*sit != sequence.back()) - { - visit = it->visitAggregate(InVisit, this); - } - } - } - } - - it->decrementDepth(); - } - - if(visit && it->postVisit) - { - it->visitAggregate(PostVisit, this); - } -} - -// -// Traverse a selection node. Same comments in binary node apply here. -// -void TIntermSelection::traverse(TIntermTraverser* it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitSelection(PreVisit, this); - - if (visit) { - it->incrementDepth(); - if (it->rightToLeft) { - if (falseBlock) - falseBlock->traverse(it); - if (trueBlock) - trueBlock->traverse(it); - condition->traverse(it); - } else { - condition->traverse(it); - if (trueBlock) - trueBlock->traverse(it); - if (falseBlock) - falseBlock->traverse(it); - } - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitSelection(PostVisit, this); -} - -// -// Traverse a loop node. Same comments in binary node apply here. -// -void TIntermLoop::traverse(TIntermTraverser* it) -{ - bool visit = true; - - if(it->preVisit) - { - visit = it->visitLoop(PreVisit, this); - } - - if(visit) - { - it->incrementDepth(); - - if(it->rightToLeft) - { - if(expr) - { - expr->traverse(it); - } - - if(body) - { - body->traverse(it); - } - - if(cond) - { - cond->traverse(it); - } - } - else - { - if(cond) - { - cond->traverse(it); - } - - if(body) - { - body->traverse(it); - } - - if(expr) - { - expr->traverse(it); - } - } - - it->decrementDepth(); - } - - if(visit && it->postVisit) - { - it->visitLoop(PostVisit, this); - } -} - -// -// Traverse a branch node. Same comments in binary node apply here. -// -void TIntermBranch::traverse(TIntermTraverser* it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitBranch(PreVisit, this); - - if (visit && expression) { - it->incrementDepth(); - expression->traverse(it); - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitBranch(PostVisit, this); -} - diff --git a/src/3rdparty/angle/src/compiler/Intermediate.cpp b/src/3rdparty/angle/src/compiler/Intermediate.cpp deleted file mode 100644 index 3b6622185d..0000000000 --- a/src/3rdparty/angle/src/compiler/Intermediate.cpp +++ /dev/null @@ -1,1442 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// Build the intermediate representation. -// - -#include -#include -#include - -#include "compiler/HashNames.h" -#include "compiler/localintermediate.h" -#include "compiler/QualifierAlive.h" -#include "compiler/RemoveTree.h" - -bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray); - -static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){ - return left > right ? left : right; -} - -const char* getOperatorString(TOperator op) { - switch (op) { - case EOpInitialize: return "="; - case EOpAssign: return "="; - case EOpAddAssign: return "+="; - case EOpSubAssign: return "-="; - case EOpDivAssign: return "/="; - - // Fall-through. - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: return "*="; - - // Fall-through. - case EOpIndexDirect: - case EOpIndexIndirect: return "[]"; - - case EOpIndexDirectStruct: return "."; - case EOpVectorSwizzle: return "."; - case EOpAdd: return "+"; - case EOpSub: return "-"; - case EOpMul: return "*"; - case EOpDiv: return "/"; - case EOpMod: UNIMPLEMENTED(); break; - case EOpEqual: return "=="; - case EOpNotEqual: return "!="; - case EOpLessThan: return "<"; - case EOpGreaterThan: return ">"; - case EOpLessThanEqual: return "<="; - case EOpGreaterThanEqual: return ">="; - - // Fall-through. - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpMatrixTimesMatrix: return "*"; - - case EOpLogicalOr: return "||"; - case EOpLogicalXor: return "^^"; - case EOpLogicalAnd: return "&&"; - case EOpNegative: return "-"; - case EOpVectorLogicalNot: return "not"; - case EOpLogicalNot: return "!"; - case EOpPostIncrement: return "++"; - case EOpPostDecrement: return "--"; - case EOpPreIncrement: return "++"; - case EOpPreDecrement: return "--"; - - // Fall-through. - case EOpConvIntToBool: - case EOpConvFloatToBool: return "bool"; - - // Fall-through. - case EOpConvBoolToFloat: - case EOpConvIntToFloat: return "float"; - - // Fall-through. - case EOpConvFloatToInt: - case EOpConvBoolToInt: return "int"; - - case EOpRadians: return "radians"; - case EOpDegrees: return "degrees"; - case EOpSin: return "sin"; - case EOpCos: return "cos"; - case EOpTan: return "tan"; - case EOpAsin: return "asin"; - case EOpAcos: return "acos"; - case EOpAtan: return "atan"; - case EOpExp: return "exp"; - case EOpLog: return "log"; - case EOpExp2: return "exp2"; - case EOpLog2: return "log2"; - case EOpSqrt: return "sqrt"; - case EOpInverseSqrt: return "inversesqrt"; - case EOpAbs: return "abs"; - case EOpSign: return "sign"; - case EOpFloor: return "floor"; - case EOpCeil: return "ceil"; - case EOpFract: return "fract"; - case EOpLength: return "length"; - case EOpNormalize: return "normalize"; - case EOpDFdx: return "dFdx"; - case EOpDFdy: return "dFdy"; - case EOpFwidth: return "fwidth"; - case EOpAny: return "any"; - case EOpAll: return "all"; - - default: break; - } - return ""; -} - -//////////////////////////////////////////////////////////////////////////// -// -// First set of functions are to help build the intermediate representation. -// These functions are not member functions of the nodes. -// They are called from parser productions. -// -///////////////////////////////////////////////////////////////////////////// - -// -// Add a terminal node for an identifier in an expression. -// -// Returns the added node. -// -TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc& line) -{ - TIntermSymbol* node = new TIntermSymbol(id, name, type); - node->setLine(line); - - return node; -} - -// -// Connect two nodes with a new parent that does a binary operation on the nodes. -// -// Returns the added node. -// -TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line, TSymbolTable& symbolTable) -{ - switch (op) { - case EOpEqual: - case EOpNotEqual: - if (left->isArray()) - return 0; - break; - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) { - return 0; - } - break; - case EOpLogicalOr: - case EOpLogicalXor: - case EOpLogicalAnd: - if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) { - return 0; - } - break; - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpMul: - if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) - return 0; - default: break; - } - - // - // First try converting the children to compatible types. - // - if (left->getType().getStruct() && right->getType().getStruct()) { - if (left->getType() != right->getType()) - return 0; - } else { - TIntermTyped* child = addConversion(op, left->getType(), right); - if (child) - right = child; - else { - child = addConversion(op, right->getType(), left); - if (child) - left = child; - else - return 0; - } - } - - // - // Need a new node holding things together then. Make - // one and promote it to the right type. - // - TIntermBinary* node = new TIntermBinary(op); - node->setLine(line); - - node->setLeft(left); - node->setRight(right); - if (!node->promote(infoSink)) - return 0; - - // - // See if we can fold constants. - // - TIntermTyped* typedReturnNode = 0; - TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion(); - TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion(); - if (leftTempConstant && rightTempConstant) { - typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink); - - if (typedReturnNode) - return typedReturnNode; - } - - return node; -} - -// -// Connect two nodes through an assignment. -// -// Returns the added node. -// -TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) -{ - // - // Like adding binary math, except the conversion can only go - // from right to left. - // - TIntermBinary* node = new TIntermBinary(op); - node->setLine(line); - - TIntermTyped* child = addConversion(op, left->getType(), right); - if (child == 0) - return 0; - - node->setLeft(left); - node->setRight(child); - if (! node->promote(infoSink)) - return 0; - - return node; -} - -// -// Connect two nodes through an index operator, where the left node is the base -// of an array or struct, and the right node is a direct or indirect offset. -// -// Returns the added node. -// The caller should set the type of the returned node. -// -TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc& line) -{ - TIntermBinary* node = new TIntermBinary(op); - node->setLine(line); - node->setLeft(base); - node->setRight(index); - - // caller should set the type - - return node; -} - -// -// Add one node as the parent of another that it operates on. -// -// Returns the added node. -// -TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc& line, TSymbolTable& symbolTable) -{ - TIntermUnary* node; - TIntermTyped* child = childNode->getAsTyped(); - - if (child == 0) { - infoSink.info.message(EPrefixInternalError, line, "Bad type in AddUnaryMath"); - return 0; - } - - switch (op) { - case EOpLogicalNot: - if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) { - return 0; - } - break; - - case EOpPostIncrement: - case EOpPreIncrement: - case EOpPostDecrement: - case EOpPreDecrement: - case EOpNegative: - if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) - return 0; - default: break; - } - - // - // Do we need to promote the operand? - // - // Note: Implicit promotions were removed from the language. - // - TBasicType newType = EbtVoid; - switch (op) { - case EOpConstructInt: newType = EbtInt; break; - case EOpConstructBool: newType = EbtBool; break; - case EOpConstructFloat: newType = EbtFloat; break; - default: break; - } - - if (newType != EbtVoid) { - child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary, - child->getNominalSize(), - child->isMatrix(), - child->isArray()), - child); - if (child == 0) - return 0; - } - - // - // For constructors, we are now done, it's all in the conversion. - // - switch (op) { - case EOpConstructInt: - case EOpConstructBool: - case EOpConstructFloat: - return child; - default: break; - } - - TIntermConstantUnion *childTempConstant = 0; - if (child->getAsConstantUnion()) - childTempConstant = child->getAsConstantUnion(); - - // - // Make a new node for the operator. - // - node = new TIntermUnary(op); - node->setLine(line); - node->setOperand(child); - - if (! node->promote(infoSink)) - return 0; - - if (childTempConstant) { - TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink); - - if (newChild) - return newChild; - } - - return node; -} - -// -// This is the safe way to change the operator on an aggregate, as it -// does lots of error checking and fixing. Especially for establishing -// a function call's operation on it's set of parameters. Sequences -// of instructions are also aggregates, but they just direnctly set -// their operator to EOpSequence. -// -// Returns an aggregate node, which could be the one passed in if -// it was already an aggregate but no operator was set. -// -TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc& line) -{ - TIntermAggregate* aggNode; - - // - // Make sure we have an aggregate. If not turn it into one. - // - if (node) { - aggNode = node->getAsAggregate(); - if (aggNode == 0 || aggNode->getOp() != EOpNull) { - // - // Make an aggregate containing this node. - // - aggNode = new TIntermAggregate(); - aggNode->getSequence().push_back(node); - } - } else - aggNode = new TIntermAggregate(); - - // - // Set the operator. - // - aggNode->setOp(op); - aggNode->setLine(line); - - return aggNode; -} - -// -// Convert one type to another. -// -// Returns the node representing the conversion, which could be the same -// node passed in if no conversion was needed. -// -// Return 0 if a conversion can't be done. -// -TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node) -{ - // - // Does the base type allow operation? - // - switch (node->getBasicType()) { - case EbtVoid: - case EbtSampler2D: - case EbtSamplerCube: - return 0; - default: break; - } - - // - // Otherwise, if types are identical, no problem - // - if (type == node->getType()) - return node; - - // - // If one's a structure, then no conversions. - // - if (type.getStruct() || node->getType().getStruct()) - return 0; - - // - // If one's an array, then no conversions. - // - if (type.isArray() || node->getType().isArray()) - return 0; - - TBasicType promoteTo; - - switch (op) { - // - // Explicit conversions - // - case EOpConstructBool: - promoteTo = EbtBool; - break; - case EOpConstructFloat: - promoteTo = EbtFloat; - break; - case EOpConstructInt: - promoteTo = EbtInt; - break; - default: - // - // implicit conversions were removed from the language. - // - if (type.getBasicType() != node->getType().getBasicType()) - return 0; - // - // Size and structure could still differ, but that's - // handled by operator promotion. - // - return node; - } - - if (node->getAsConstantUnion()) { - - return (promoteConstantUnion(promoteTo, node->getAsConstantUnion())); - } else { - - // - // Add a new newNode for the conversion. - // - TIntermUnary* newNode = 0; - - TOperator newOp = EOpNull; - switch (promoteTo) { - case EbtFloat: - switch (node->getBasicType()) { - case EbtInt: newOp = EOpConvIntToFloat; break; - case EbtBool: newOp = EOpConvBoolToFloat; break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); - return 0; - } - break; - case EbtBool: - switch (node->getBasicType()) { - case EbtInt: newOp = EOpConvIntToBool; break; - case EbtFloat: newOp = EOpConvFloatToBool; break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); - return 0; - } - break; - case EbtInt: - switch (node->getBasicType()) { - case EbtBool: newOp = EOpConvBoolToInt; break; - case EbtFloat: newOp = EOpConvFloatToInt; break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); - return 0; - } - break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion type"); - return 0; - } - - TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray()); - newNode = new TIntermUnary(newOp, type); - newNode->setLine(node->getLine()); - newNode->setOperand(node); - - return newNode; - } -} - -// -// Safe way to combine two nodes into an aggregate. Works with null pointers, -// a node that's not a aggregate yet, etc. -// -// Returns the resulting aggregate, unless 0 was passed in for -// both existing nodes. -// -TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& line) -{ - if (left == 0 && right == 0) - return 0; - - TIntermAggregate* aggNode = 0; - if (left) - aggNode = left->getAsAggregate(); - if (!aggNode || aggNode->getOp() != EOpNull) { - aggNode = new TIntermAggregate; - if (left) - aggNode->getSequence().push_back(left); - } - - if (right) - aggNode->getSequence().push_back(right); - - aggNode->setLine(line); - - return aggNode; -} - -// -// Turn an existing node into an aggregate. -// -// Returns an aggregate, unless 0 was passed in for the existing node. -// -TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& line) -{ - if (node == 0) - return 0; - - TIntermAggregate* aggNode = new TIntermAggregate; - aggNode->getSequence().push_back(node); - aggNode->setLine(line); - - return aggNode; -} - -// -// For "if" test nodes. There are three children; a condition, -// a true path, and a false path. The two paths are in the -// nodePair. -// -// Returns the selection node created. -// -TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& line) -{ - // - // For compile time constant selections, prune the code and - // test now. - // - - if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) { - if (cond->getAsConstantUnion()->getBConst(0) == true) - return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL; - else - return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL; - } - - TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2); - node->setLine(line); - - return node; -} - - -TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) -{ - if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) { - return right; - } else { - TIntermTyped *commaAggregate = growAggregate(left, right, line); - commaAggregate->getAsAggregate()->setOp(EOpComma); - commaAggregate->setType(right->getType()); - commaAggregate->getTypePointer()->setQualifier(EvqTemporary); - return commaAggregate; - } -} - -// -// For "?:" test nodes. There are three children; a condition, -// a true path, and a false path. The two paths are specified -// as separate parameters. -// -// Returns the selection node created, or 0 if one could not be. -// -TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& line) -{ - // - // Get compatible types. - // - TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock); - if (child) - falseBlock = child; - else { - child = addConversion(EOpSequence, falseBlock->getType(), trueBlock); - if (child) - trueBlock = child; - else - return 0; - } - - // - // See if all the operands are constant, then fold it otherwise not. - // - - if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) { - if (cond->getAsConstantUnion()->getBConst(0)) - return trueBlock; - else - return falseBlock; - } - - // - // Make a selection node. - // - TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType()); - node->getTypePointer()->setQualifier(EvqTemporary); - node->setLine(line); - - return node; -} - -// -// Constant terminal nodes. Has a union that contains bool, float or int constants -// -// Returns the constant union node created. -// - -TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc& line) -{ - TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t); - node->setLine(line); - - return node; -} - -TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& line) -{ - - TIntermAggregate* node = new TIntermAggregate(EOpSequence); - - node->setLine(line); - TIntermConstantUnion* constIntNode; - TIntermSequence &sequenceVector = node->getSequence(); - ConstantUnion* unionArray; - - for (int i = 0; i < fields.num; i++) { - unionArray = new ConstantUnion[1]; - unionArray->setIConst(fields.offsets[i]); - constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line); - sequenceVector.push_back(constIntNode); - } - - return node; -} - -// -// Create loop nodes. -// -TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc& line) -{ - TIntermNode* node = new TIntermLoop(type, init, cond, expr, body); - node->setLine(line); - - return node; -} - -// -// Add branches. -// -TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& line) -{ - return addBranch(branchOp, 0, line); -} - -TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& line) -{ - TIntermBranch* node = new TIntermBranch(branchOp, expression); - node->setLine(line); - - return node; -} - -// -// This is to be executed once the final root is put on top by the parsing -// process. -// -bool TIntermediate::postProcess(TIntermNode* root) -{ - if (root == 0) - return true; - - // - // First, finish off the top level sequence, if any - // - TIntermAggregate* aggRoot = root->getAsAggregate(); - if (aggRoot && aggRoot->getOp() == EOpNull) - aggRoot->setOp(EOpSequence); - - return true; -} - -// -// This deletes the tree. -// -void TIntermediate::remove(TIntermNode* root) -{ - if (root) - RemoveAllTreeNodes(root); -} - -//////////////////////////////////////////////////////////////// -// -// Member functions of the nodes used for building the tree. -// -//////////////////////////////////////////////////////////////// - -// -// Say whether or not an operation node changes the value of a variable. -// -// Returns true if state is modified. -// -bool TIntermOperator::modifiesState() const -{ - switch (op) { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - case EOpAssign: - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - case EOpDivAssign: - return true; - default: - return false; - } -} - -// -// returns true if the operator is for one of the constructors -// -bool TIntermOperator::isConstructor() const -{ - switch (op) { - case EOpConstructVec2: - case EOpConstructVec3: - case EOpConstructVec4: - case EOpConstructMat2: - case EOpConstructMat3: - case EOpConstructMat4: - case EOpConstructFloat: - case EOpConstructIVec2: - case EOpConstructIVec3: - case EOpConstructIVec4: - case EOpConstructInt: - case EOpConstructBVec2: - case EOpConstructBVec3: - case EOpConstructBVec4: - case EOpConstructBool: - case EOpConstructStruct: - return true; - default: - return false; - } -} -// -// Make sure the type of a unary operator is appropriate for its -// combination of operation and operand type. -// -// Returns false in nothing makes sense. -// -bool TIntermUnary::promote(TInfoSink&) -{ - switch (op) { - case EOpLogicalNot: - if (operand->getBasicType() != EbtBool) - return false; - break; - case EOpNegative: - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - if (operand->getBasicType() == EbtBool) - return false; - break; - - // operators for built-ins are already type checked against their prototype - case EOpAny: - case EOpAll: - case EOpVectorLogicalNot: - return true; - - default: - if (operand->getBasicType() != EbtFloat) - return false; - } - - setType(operand->getType()); - type.setQualifier(EvqTemporary); - - return true; -} - -// -// Establishes the type of the resultant operation, as well as -// makes the operator the correct one for the operands. -// -// Returns false if operator can't work on operands. -// -bool TIntermBinary::promote(TInfoSink& infoSink) -{ - // This function only handles scalars, vectors, and matrices. - if (left->isArray() || right->isArray()) { - infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operation for arrays"); - return false; - } - - // GLSL ES 2.0 does not support implicit type casting. - // So the basic type should always match. - if (left->getBasicType() != right->getBasicType()) - return false; - - // - // Base assumption: just make the type the same as the left - // operand. Then only deviations from this need be coded. - // - setType(left->getType()); - - // The result gets promoted to the highest precision. - TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision()); - getTypePointer()->setPrecision(higherPrecision); - - // Binary operations results in temporary variables unless both - // operands are const. - if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) { - getTypePointer()->setQualifier(EvqTemporary); - } - - int size = std::max(left->getNominalSize(), right->getNominalSize()); - - // - // All scalars. Code after this test assumes this case is removed! - // - if (size == 1) { - switch (op) { - // - // Promote to conditional - // - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - setType(TType(EbtBool, EbpUndefined)); - break; - - // - // And and Or operate on conditionals - // - case EOpLogicalAnd: - case EOpLogicalOr: - // Both operands must be of type bool. - if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool) - return false; - setType(TType(EbtBool, EbpUndefined)); - break; - - default: - break; - } - return true; - } - - // If we reach here, at least one of the operands is vector or matrix. - // The other operand could be a scalar, vector, or matrix. - // Are the sizes compatible? - // - if (left->getNominalSize() != right->getNominalSize()) { - // If the nominal size of operands do not match: - // One of them must be scalar. - if (left->getNominalSize() != 1 && right->getNominalSize() != 1) - return false; - // Operator cannot be of type pure assignment. - if (op == EOpAssign || op == EOpInitialize) - return false; - } - - // - // Can these two operands be combined? - // - TBasicType basicType = left->getBasicType(); - switch (op) { - case EOpMul: - if (!left->isMatrix() && right->isMatrix()) { - if (left->isVector()) - op = EOpVectorTimesMatrix; - else { - op = EOpMatrixTimesScalar; - setType(TType(basicType, higherPrecision, EvqTemporary, size, true)); - } - } else if (left->isMatrix() && !right->isMatrix()) { - if (right->isVector()) { - op = EOpMatrixTimesVector; - setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); - } else { - op = EOpMatrixTimesScalar; - } - } else if (left->isMatrix() && right->isMatrix()) { - op = EOpMatrixTimesMatrix; - } else if (!left->isMatrix() && !right->isMatrix()) { - if (left->isVector() && right->isVector()) { - // leave as component product - } else if (left->isVector() || right->isVector()) { - op = EOpVectorTimesScalar; - setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); - } - } else { - infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses"); - return false; - } - break; - case EOpMulAssign: - if (!left->isMatrix() && right->isMatrix()) { - if (left->isVector()) - op = EOpVectorTimesMatrixAssign; - else { - return false; - } - } else if (left->isMatrix() && !right->isMatrix()) { - if (right->isVector()) { - return false; - } else { - op = EOpMatrixTimesScalarAssign; - } - } else if (left->isMatrix() && right->isMatrix()) { - op = EOpMatrixTimesMatrixAssign; - } else if (!left->isMatrix() && !right->isMatrix()) { - if (left->isVector() && right->isVector()) { - // leave as component product - } else if (left->isVector() || right->isVector()) { - if (! left->isVector()) - return false; - op = EOpVectorTimesScalarAssign; - setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); - } - } else { - infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses"); - return false; - } - break; - - case EOpAssign: - case EOpInitialize: - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - if ((left->isMatrix() && right->isVector()) || - (left->isVector() && right->isMatrix())) - return false; - setType(TType(basicType, higherPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix())); - break; - - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - if ((left->isMatrix() && right->isVector()) || - (left->isVector() && right->isMatrix())) - return false; - setType(TType(EbtBool, EbpUndefined)); - break; - - default: - return false; - } - - return true; -} - -bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) -{ - const TFieldList& fields = leftNodeType.getStruct()->fields(); - - size_t structSize = fields.size(); - size_t index = 0; - - for (size_t j = 0; j < structSize; j++) { - size_t size = fields[j]->type()->getObjectSize(); - for (size_t i = 0; i < size; i++) { - if (fields[j]->type()->getBasicType() == EbtStruct) { - if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index])) - return false; - } else { - if (leftUnionArray[index] != rightUnionArray[index]) - return false; - index++; - } - } - } - return true; -} - -bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) -{ - if (leftNodeType.isArray()) { - TType typeWithoutArrayness = leftNodeType; - typeWithoutArrayness.clearArrayness(); - - size_t arraySize = leftNodeType.getArraySize(); - - for (size_t i = 0; i < arraySize; ++i) { - size_t offset = typeWithoutArrayness.getObjectSize() * i; - if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset])) - return false; - } - } else - return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray); - - return true; -} - -// -// The fold functions see if an operation on a constant can be done in place, -// without generating run-time code. -// -// Returns the node to keep using, which may or may not be the node passed in. -// - -TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink) -{ - ConstantUnion *unionArray = getUnionArrayPointer(); - size_t objectSize = getType().getObjectSize(); - - if (constantNode) { // binary operations - TIntermConstantUnion *node = constantNode->getAsConstantUnion(); - ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); - TType returnType = getType(); - - // for a case like float f = 1.2 + vec4(2,3,4,5); - if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) { - rightUnionArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; ++i) - rightUnionArray[i] = *node->getUnionArrayPointer(); - returnType = getType(); - } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) { - // for a case like float f = vec4(2,3,4,5) + 1.2; - unionArray = new ConstantUnion[constantNode->getType().getObjectSize()]; - for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i) - unionArray[i] = *getUnionArrayPointer(); - returnType = node->getType(); - objectSize = constantNode->getType().getObjectSize(); - } - - ConstantUnion* tempConstArray = 0; - TIntermConstantUnion *tempNode; - - bool boolNodeFlag = false; - switch(op) { - case EOpAdd: - tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] + rightUnionArray[i]; - } - break; - case EOpSub: - tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] - rightUnionArray[i]; - } - break; - - case EOpMul: - case EOpVectorTimesScalar: - case EOpMatrixTimesScalar: - tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] * rightUnionArray[i]; - } - break; - case EOpMatrixTimesMatrix: - if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) { - infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix multiply"); - return 0; - } - {// support MSVC++6.0 - int size = getNominalSize(); - tempConstArray = new ConstantUnion[size*size]; - for (int row = 0; row < size; row++) { - for (int column = 0; column < size; column++) { - tempConstArray[size * column + row].setFConst(0.0f); - for (int i = 0; i < size; i++) { - tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst())); - } - } - } - } - break; - case EOpDiv: - tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) { - switch (getType().getBasicType()) { - case EbtFloat: - if (rightUnionArray[i] == 0.0f) { - infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding"); - tempConstArray[i].setFConst(unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX); - } else - tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst()); - break; - - case EbtInt: - if (rightUnionArray[i] == 0) { - infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding"); - tempConstArray[i].setIConst(INT_MAX); - } else - tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst()); - break; - default: - infoSink.info.message(EPrefixInternalError, getLine(), "Constant folding cannot be done for \"/\""); - return 0; - } - } - } - break; - - case EOpMatrixTimesVector: - if (node->getBasicType() != EbtFloat) { - infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix times vector"); - return 0; - } - tempConstArray = new ConstantUnion[getNominalSize()]; - - {// support MSVC++6.0 - for (int size = getNominalSize(), i = 0; i < size; i++) { - tempConstArray[i].setFConst(0.0f); - for (int j = 0; j < size; j++) { - tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst())); - } - } - } - - tempNode = new TIntermConstantUnion(tempConstArray, node->getType()); - tempNode->setLine(getLine()); - - return tempNode; - - case EOpVectorTimesMatrix: - if (getType().getBasicType() != EbtFloat) { - infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for vector times matrix"); - return 0; - } - - tempConstArray = new ConstantUnion[getNominalSize()]; - {// support MSVC++6.0 - for (int size = getNominalSize(), i = 0; i < size; i++) { - tempConstArray[i].setFConst(0.0f); - for (int j = 0; j < size; j++) { - tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst())); - } - } - } - break; - - case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently - tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] && rightUnionArray[i]; - } - break; - - case EOpLogicalOr: // this code is written for possible future use, will not get executed currently - tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] || rightUnionArray[i]; - } - break; - - case EOpLogicalXor: - tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) - switch (getType().getBasicType()) { - case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break; - default: assert(false && "Default missing"); - } - } - break; - - case EOpLessThan: - assert(objectSize == 1); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(*unionArray < *rightUnionArray); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - case EOpGreaterThan: - assert(objectSize == 1); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(*unionArray > *rightUnionArray); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - case EOpLessThanEqual: - { - assert(objectSize == 1); - ConstantUnion constant; - constant.setBConst(*unionArray > *rightUnionArray); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(!constant.getBConst()); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - } - case EOpGreaterThanEqual: - { - assert(objectSize == 1); - ConstantUnion constant; - constant.setBConst(*unionArray < *rightUnionArray); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(!constant.getBConst()); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - } - - case EOpEqual: - if (getType().getBasicType() == EbtStruct) { - if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) - boolNodeFlag = true; - } else { - for (size_t i = 0; i < objectSize; i++) { - if (unionArray[i] != rightUnionArray[i]) { - boolNodeFlag = true; - break; // break out of for loop - } - } - } - - tempConstArray = new ConstantUnion[1]; - if (!boolNodeFlag) { - tempConstArray->setBConst(true); - } - else { - tempConstArray->setBConst(false); - } - - tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); - tempNode->setLine(getLine()); - - return tempNode; - - case EOpNotEqual: - if (getType().getBasicType() == EbtStruct) { - if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) - boolNodeFlag = true; - } else { - for (size_t i = 0; i < objectSize; i++) { - if (unionArray[i] == rightUnionArray[i]) { - boolNodeFlag = true; - break; // break out of for loop - } - } - } - - tempConstArray = new ConstantUnion[1]; - if (!boolNodeFlag) { - tempConstArray->setBConst(true); - } - else { - tempConstArray->setBConst(false); - } - - tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); - tempNode->setLine(getLine()); - - return tempNode; - - default: - infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operator for constant folding"); - return 0; - } - tempNode = new TIntermConstantUnion(tempConstArray, returnType); - tempNode->setLine(getLine()); - - return tempNode; - } else { - // - // Do unary operations - // - TIntermConstantUnion *newNode = 0; - ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) { - switch(op) { - case EOpNegative: - switch (getType().getBasicType()) { - case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break; - case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break; - default: - infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); - return 0; - } - break; - case EOpLogicalNot: // this code is written for possible future use, will not get executed currently - switch (getType().getBasicType()) { - case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break; - default: - infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); - return 0; - } - break; - default: - return 0; - } - } - newNode = new TIntermConstantUnion(tempConstArray, getType()); - newNode->setLine(getLine()); - return newNode; - } -} - -TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) -{ - size_t size = node->getType().getObjectSize(); - - ConstantUnion *leftUnionArray = new ConstantUnion[size]; - - for (size_t i = 0; i < size; i++) { - - switch (promoteTo) { - case EbtFloat: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setFConst(static_cast(node->getIConst(i))); - break; - case EbtBool: - leftUnionArray[i].setFConst(static_cast(node->getBConst(i))); - break; - case EbtFloat: - leftUnionArray[i].setFConst(static_cast(node->getFConst(i))); - break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); - return 0; - } - break; - case EbtInt: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setIConst(static_cast(node->getIConst(i))); - break; - case EbtBool: - leftUnionArray[i].setIConst(static_cast(node->getBConst(i))); - break; - case EbtFloat: - leftUnionArray[i].setIConst(static_cast(node->getFConst(i))); - break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); - return 0; - } - break; - case EbtBool: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setBConst(node->getIConst(i) != 0); - break; - case EbtBool: - leftUnionArray[i].setBConst(node->getBConst(i)); - break; - case EbtFloat: - leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f); - break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); - return 0; - } - - break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found"); - return 0; - } - - } - - const TType& t = node->getType(); - - return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine()); -} - -// static -TString TIntermTraverser::hash(const TString& name, ShHashFunction64 hashFunction) -{ - if (hashFunction == NULL || name.empty()) - return name; - khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length()); - TStringStream stream; - stream << HASHED_NAME_PREFIX << std::hex << number; - TString hashedName = stream.str(); - return hashedName; -} diff --git a/src/3rdparty/angle/src/compiler/MMap.h b/src/3rdparty/angle/src/compiler/MMap.h deleted file mode 100644 index a308671514..0000000000 --- a/src/3rdparty/angle/src/compiler/MMap.h +++ /dev/null @@ -1,56 +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. -// - -#ifndef _MMAP_INCLUDED_ -#define _MMAP_INCLUDED_ - -// -// Encapsulate memory mapped files -// - -class TMMap { -public: - TMMap(const char* fileName) : - fSize(-1), // -1 is the error value returned by GetFileSize() - fp(NULL), - fBuff(0) // 0 is the error value returned by MapViewOfFile() - { - if ((fp = fopen(fileName, "r")) == NULL) - return; - char c = getc(fp); - fSize = 0; - while (c != EOF) { - fSize++; - c = getc(fp); - } - if (c == EOF) - fSize++; - rewind(fp); - fBuff = (char*)malloc(sizeof(char) * fSize); - int count = 0; - c = getc(fp); - while (c != EOF) { - fBuff[count++] = c; - c = getc(fp); - } - fBuff[count++] = c; - } - - char* getData() { return fBuff; } - int getSize() { return fSize; } - - ~TMMap() { - if (fp != NULL) - fclose(fp); - } - -private: - int fSize; // size of file to map in - FILE *fp; - char* fBuff; // the actual data; -}; - -#endif // _MMAP_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/MapLongVariableNames.cpp b/src/3rdparty/angle/src/compiler/MapLongVariableNames.cpp deleted file mode 100644 index a41d20f4e8..0000000000 --- a/src/3rdparty/angle/src/compiler/MapLongVariableNames.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/MapLongVariableNames.h" - -namespace { - -TString mapLongName(size_t id, const TString& name, bool isGlobal) -{ - ASSERT(name.size() > MAX_SHORTENED_IDENTIFIER_SIZE); - TStringStream stream; - stream << "webgl_"; - if (isGlobal) - stream << "g"; - stream << id; - if (name[0] != '_') - stream << "_"; - stream << name.substr(0, MAX_SHORTENED_IDENTIFIER_SIZE - stream.str().size()); - return stream.str(); -} - -LongNameMap* gLongNameMapInstance = NULL; - -} // anonymous namespace - -LongNameMap::LongNameMap() - : refCount(0) -{ -} - -LongNameMap::~LongNameMap() -{ -} - -// static -LongNameMap* LongNameMap::GetInstance() -{ - if (gLongNameMapInstance == NULL) - gLongNameMapInstance = new LongNameMap; - gLongNameMapInstance->refCount++; - return gLongNameMapInstance; -} - -void LongNameMap::Release() -{ - ASSERT(gLongNameMapInstance == this); - ASSERT(refCount > 0); - refCount--; - if (refCount == 0) { - delete gLongNameMapInstance; - gLongNameMapInstance = NULL; - } -} - -const char* LongNameMap::Find(const char* originalName) const -{ - std::map::const_iterator it = mLongNameMap.find( - originalName); - if (it != mLongNameMap.end()) - return (*it).second.c_str(); - return NULL; -} - -void LongNameMap::Insert(const char* originalName, const char* mappedName) -{ - mLongNameMap.insert(std::map::value_type( - originalName, mappedName)); -} - -size_t LongNameMap::Size() const -{ - return mLongNameMap.size(); -} - -MapLongVariableNames::MapLongVariableNames(LongNameMap* globalMap) -{ - ASSERT(globalMap); - mGlobalMap = globalMap; -} - -void MapLongVariableNames::visitSymbol(TIntermSymbol* symbol) -{ - ASSERT(symbol != NULL); - if (symbol->getSymbol().size() > MAX_SHORTENED_IDENTIFIER_SIZE) { - switch (symbol->getQualifier()) { - case EvqVaryingIn: - case EvqVaryingOut: - case EvqInvariantVaryingIn: - case EvqInvariantVaryingOut: - case EvqUniform: - symbol->setSymbol( - mapGlobalLongName(symbol->getSymbol())); - break; - default: - symbol->setSymbol( - mapLongName(symbol->getId(), symbol->getSymbol(), false)); - break; - }; - } -} - -bool MapLongVariableNames::visitLoop(Visit, TIntermLoop* node) -{ - if (node->getInit()) - node->getInit()->traverse(this); - return true; -} - -TString MapLongVariableNames::mapGlobalLongName(const TString& name) -{ - ASSERT(mGlobalMap); - const char* mappedName = mGlobalMap->Find(name.c_str()); - if (mappedName != NULL) - return mappedName; - size_t id = mGlobalMap->Size(); - TString rt = mapLongName(id, name, true); - mGlobalMap->Insert(name.c_str(), rt.c_str()); - return rt; -} diff --git a/src/3rdparty/angle/src/compiler/MapLongVariableNames.h b/src/3rdparty/angle/src/compiler/MapLongVariableNames.h deleted file mode 100644 index d6352acb4b..0000000000 --- a/src/3rdparty/angle/src/compiler/MapLongVariableNames.h +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_MAP_LONG_VARIABLE_NAMES_H_ -#define COMPILER_MAP_LONG_VARIABLE_NAMES_H_ - -#include "GLSLANG/ShaderLang.h" - -#include "compiler/intermediate.h" -#include "compiler/VariableInfo.h" - -// This size does not include '\0' in the end. -#define MAX_SHORTENED_IDENTIFIER_SIZE 32 - -// This is a ref-counted singleton. GetInstance() returns a pointer to the -// singleton, and after use, call Release(). GetInstance() and Release() should -// be paired. -class LongNameMap { -public: - static LongNameMap* GetInstance(); - void Release(); - - // Return the mapped name if is in the map; - // otherwise, return NULL. - const char* Find(const char* originalName) const; - - // Insert a pair into the map. - void Insert(const char* originalName, const char* mappedName); - - // Return the number of entries in the map. - size_t Size() const; - -private: - LongNameMap(); - ~LongNameMap(); - - size_t refCount; - std::map mLongNameMap; -}; - -// Traverses intermediate tree to map attributes and uniforms names that are -// longer than MAX_SHORTENED_IDENTIFIER_SIZE to MAX_SHORTENED_IDENTIFIER_SIZE. -class MapLongVariableNames : public TIntermTraverser { -public: - MapLongVariableNames(LongNameMap* globalMap); - - virtual void visitSymbol(TIntermSymbol*); - virtual bool visitLoop(Visit, TIntermLoop*); - -private: - TString mapGlobalLongName(const TString& name); - - LongNameMap* mGlobalMap; -}; - -#endif // COMPILER_MAP_LONG_VARIABLE_NAMES_H_ diff --git a/src/3rdparty/angle/src/compiler/OutputESSL.cpp b/src/3rdparty/angle/src/compiler/OutputESSL.cpp deleted file mode 100644 index c2048f1cec..0000000000 --- a/src/3rdparty/angle/src/compiler/OutputESSL.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/OutputESSL.h" - -TOutputESSL::TOutputESSL(TInfoSinkBase& objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap& nameMap, - TSymbolTable& symbolTable) - : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable) -{ -} - -bool TOutputESSL::writeVariablePrecision(TPrecision precision) -{ - if (precision == EbpUndefined) - return false; - - TInfoSinkBase& out = objSink(); - out << getPrecisionString(precision); - return true; -} diff --git a/src/3rdparty/angle/src/compiler/OutputESSL.h b/src/3rdparty/angle/src/compiler/OutputESSL.h deleted file mode 100644 index 05db96e497..0000000000 --- a/src/3rdparty/angle/src/compiler/OutputESSL.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef CROSSCOMPILERGLSL_OUTPUTESSL_H_ -#define CROSSCOMPILERGLSL_OUTPUTESSL_H_ - -#include "compiler/OutputGLSLBase.h" - -class TOutputESSL : public TOutputGLSLBase -{ -public: - TOutputESSL(TInfoSinkBase& objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap& nameMap, - TSymbolTable& symbolTable); - -protected: - virtual bool writeVariablePrecision(TPrecision precision); -}; - -#endif // CROSSCOMPILERGLSL_OUTPUTESSL_H_ diff --git a/src/3rdparty/angle/src/compiler/OutputGLSL.cpp b/src/3rdparty/angle/src/compiler/OutputGLSL.cpp deleted file mode 100644 index 10a451c0d7..0000000000 --- a/src/3rdparty/angle/src/compiler/OutputGLSL.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/OutputGLSL.h" - -TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap& nameMap, - TSymbolTable& symbolTable) - : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable) -{ -} - -bool TOutputGLSL::writeVariablePrecision(TPrecision) -{ - return false; -} - -void TOutputGLSL::visitSymbol(TIntermSymbol* node) -{ - TInfoSinkBase& out = objSink(); - - if (node->getSymbol() == "gl_FragDepthEXT") - { - out << "gl_FragDepth"; - } - else - { - TOutputGLSLBase::visitSymbol(node); - } -} diff --git a/src/3rdparty/angle/src/compiler/OutputGLSL.h b/src/3rdparty/angle/src/compiler/OutputGLSL.h deleted file mode 100644 index fa68ac8103..0000000000 --- a/src/3rdparty/angle/src/compiler/OutputGLSL.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef CROSSCOMPILERGLSL_OUTPUTGLSL_H_ -#define CROSSCOMPILERGLSL_OUTPUTGLSL_H_ - -#include "compiler/OutputGLSLBase.h" - -class TOutputGLSL : public TOutputGLSLBase -{ -public: - TOutputGLSL(TInfoSinkBase& objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap& nameMap, - TSymbolTable& symbolTable); - -protected: - virtual bool writeVariablePrecision(TPrecision); - virtual void visitSymbol(TIntermSymbol* node); -}; - -#endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp deleted file mode 100644 index d677c75633..0000000000 --- a/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp +++ /dev/null @@ -1,817 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/OutputGLSLBase.h" -#include "compiler/debug.h" - -#include - -namespace -{ -TString arrayBrackets(const TType& type) -{ - ASSERT(type.isArray()); - TInfoSinkBase out; - out << "[" << type.getArraySize() << "]"; - return TString(out.c_str()); -} - -bool isSingleStatement(TIntermNode* node) { - if (const TIntermAggregate* aggregate = node->getAsAggregate()) - { - return (aggregate->getOp() != EOpFunction) && - (aggregate->getOp() != EOpSequence); - } - else if (const TIntermSelection* selection = node->getAsSelectionNode()) - { - // Ternary operators are usually part of an assignment operator. - // This handles those rare cases in which they are all by themselves. - return selection->usesTernaryOperator(); - } - else if (node->getAsLoopNode()) - { - return false; - } - return true; -} -} // namespace - -TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap& nameMap, - TSymbolTable& symbolTable) - : TIntermTraverser(true, true, true), - mObjSink(objSink), - mDeclaringVariables(false), - mClampingStrategy(clampingStrategy), - mHashFunction(hashFunction), - mNameMap(nameMap), - mSymbolTable(symbolTable) -{ -} - -void TOutputGLSLBase::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr) -{ - TInfoSinkBase& out = objSink(); - if (visit == PreVisit && preStr) - { - out << preStr; - } - else if (visit == InVisit && inStr) - { - out << inStr; - } - else if (visit == PostVisit && postStr) - { - out << postStr; - } -} - -void TOutputGLSLBase::writeVariableType(const TType& type) -{ - TInfoSinkBase& out = objSink(); - TQualifier qualifier = type.getQualifier(); - // TODO(alokp): Validate qualifier for variable declarations. - if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal)) - out << type.getQualifierString() << " "; - // Declare the struct if we have not done so already. - if ((type.getBasicType() == EbtStruct) && !structDeclared(type.getStruct())) - { - declareStruct(type.getStruct()); - } - else - { - if (writeVariablePrecision(type.getPrecision())) - out << " "; - out << getTypeName(type); - } -} - -void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence& args) -{ - TInfoSinkBase& out = objSink(); - for (TIntermSequence::const_iterator iter = args.begin(); - iter != args.end(); ++iter) - { - const TIntermSymbol* arg = (*iter)->getAsSymbolNode(); - ASSERT(arg != NULL); - - const TType& type = arg->getType(); - writeVariableType(type); - - const TString& name = arg->getSymbol(); - if (!name.empty()) - out << " " << hashName(name); - if (type.isArray()) - out << arrayBrackets(type); - - // Put a comma if this is not the last argument. - if (iter != args.end() - 1) - out << ", "; - } -} - -const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type, - const ConstantUnion* pConstUnion) -{ - TInfoSinkBase& out = objSink(); - - if (type.getBasicType() == EbtStruct) - { - const TStructure* structure = type.getStruct(); - out << hashName(structure->name()) << "("; - - const TFieldList& fields = structure->fields(); - for (size_t i = 0; i < fields.size(); ++i) - { - const TType* fieldType = fields[i]->type(); - ASSERT(fieldType != NULL); - pConstUnion = writeConstantUnion(*fieldType, pConstUnion); - if (i != fields.size() - 1) out << ", "; - } - out << ")"; - } - else - { - size_t size = type.getObjectSize(); - bool writeType = size > 1; - if (writeType) out << getTypeName(type) << "("; - for (size_t i = 0; i < size; ++i, ++pConstUnion) - { - switch (pConstUnion->getType()) - { - case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, pConstUnion->getFConst())); break; - case EbtInt: out << pConstUnion->getIConst(); break; - case EbtBool: out << pConstUnion->getBConst(); break; - default: UNREACHABLE(); - } - if (i != size - 1) out << ", "; - } - if (writeType) out << ")"; - } - return pConstUnion; -} - -void TOutputGLSLBase::visitSymbol(TIntermSymbol* node) -{ - TInfoSinkBase& out = objSink(); - if (mLoopUnroll.NeedsToReplaceSymbolWithValue(node)) - out << mLoopUnroll.GetLoopIndexValue(node); - else - out << hashVariableName(node->getSymbol()); - - if (mDeclaringVariables && node->getType().isArray()) - out << arrayBrackets(node->getType()); -} - -void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion* node) -{ - writeConstantUnion(node->getType(), node->getUnionArrayPointer()); -} - -bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node) -{ - bool visitChildren = true; - TInfoSinkBase& out = objSink(); - switch (node->getOp()) - { - case EOpInitialize: - if (visit == InVisit) - { - out << " = "; - // RHS of initialize is not being declared. - mDeclaringVariables = false; - } - break; - case EOpAssign: writeTriplet(visit, "(", " = ", ")"); break; - case EOpAddAssign: writeTriplet(visit, "(", " += ", ")"); break; - case EOpSubAssign: writeTriplet(visit, "(", " -= ", ")"); break; - case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break; - // Notice the fall-through. - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - writeTriplet(visit, "(", " *= ", ")"); - break; - - case EOpIndexDirect: - writeTriplet(visit, NULL, "[", "]"); - break; - case EOpIndexIndirect: - if (node->getAddIndexClamp()) - { - if (visit == InVisit) - { - if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) { - out << "[int(clamp(float("; - } else { - out << "[webgl_int_clamp("; - } - } - else if (visit == PostVisit) - { - int maxSize; - TIntermTyped *left = node->getLeft(); - TType leftType = left->getType(); - - if (left->isArray()) - { - // The shader will fail validation if the array length is not > 0. - maxSize = leftType.getArraySize() - 1; - } - else - { - maxSize = leftType.getNominalSize() - 1; - } - - if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) { - out << "), 0.0, float(" << maxSize << ")))]"; - } else { - out << ", 0, " << maxSize << ")]"; - } - } - } - else - { - writeTriplet(visit, NULL, "[", "]"); - } - break; - case EOpIndexDirectStruct: - if (visit == InVisit) - { - // Here we are writing out "foo.bar", where "foo" is struct - // and "bar" is field. In AST, it is represented as a binary - // node, where left child represents "foo" and right child "bar". - // The node itself represents ".". The struct field "bar" is - // actually stored as an index into TStructure::fields. - out << "."; - const TStructure* structure = node->getLeft()->getType().getStruct(); - const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion(); - const TField* field = structure->fields()[index->getIConst(0)]; - - TString fieldName = field->name(); - if (!mSymbolTable.findBuiltIn(structure->name())) - fieldName = hashName(fieldName); - - out << fieldName; - visitChildren = false; - } - break; - case EOpVectorSwizzle: - if (visit == InVisit) - { - out << "."; - TIntermAggregate* rightChild = node->getRight()->getAsAggregate(); - TIntermSequence& sequence = rightChild->getSequence(); - for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit) - { - TIntermConstantUnion* element = (*sit)->getAsConstantUnion(); - ASSERT(element->getBasicType() == EbtInt); - ASSERT(element->getNominalSize() == 1); - const ConstantUnion& data = element->getUnionArrayPointer()[0]; - ASSERT(data.getType() == EbtInt); - switch (data.getIConst()) - { - case 0: out << "x"; break; - case 1: out << "y"; break; - case 2: out << "z"; break; - case 3: out << "w"; break; - default: UNREACHABLE(); break; - } - } - visitChildren = false; - } - break; - - case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break; - case EOpSub: writeTriplet(visit, "(", " - ", ")"); break; - case EOpMul: writeTriplet(visit, "(", " * ", ")"); break; - case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break; - case EOpMod: UNIMPLEMENTED(); break; - case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break; - case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break; - case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break; - case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break; - case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break; - case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break; - - // Notice the fall-through. - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpMatrixTimesMatrix: - writeTriplet(visit, "(", " * ", ")"); - break; - - case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break; - case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break; - case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break; - default: UNREACHABLE(); break; - } - - return visitChildren; -} - -bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node) -{ - TString preString; - TString postString = ")"; - - switch (node->getOp()) - { - case EOpNegative: preString = "(-"; break; - case EOpVectorLogicalNot: preString = "not("; break; - case EOpLogicalNot: preString = "(!"; break; - - case EOpPostIncrement: preString = "("; postString = "++)"; break; - case EOpPostDecrement: preString = "("; postString = "--)"; break; - case EOpPreIncrement: preString = "(++"; break; - case EOpPreDecrement: preString = "(--"; break; - - case EOpConvIntToBool: - case EOpConvFloatToBool: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: preString = "bool("; break; - case 2: preString = "bvec2("; break; - case 3: preString = "bvec3("; break; - case 4: preString = "bvec4("; break; - default: UNREACHABLE(); - } - break; - case EOpConvBoolToFloat: - case EOpConvIntToFloat: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: preString = "float("; break; - case 2: preString = "vec2("; break; - case 3: preString = "vec3("; break; - case 4: preString = "vec4("; break; - default: UNREACHABLE(); - } - break; - case EOpConvFloatToInt: - case EOpConvBoolToInt: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: preString = "int("; break; - case 2: preString = "ivec2("; break; - case 3: preString = "ivec3("; break; - case 4: preString = "ivec4("; break; - default: UNREACHABLE(); - } - break; - - case EOpRadians: preString = "radians("; break; - case EOpDegrees: preString = "degrees("; break; - case EOpSin: preString = "sin("; break; - case EOpCos: preString = "cos("; break; - case EOpTan: preString = "tan("; break; - case EOpAsin: preString = "asin("; break; - case EOpAcos: preString = "acos("; break; - case EOpAtan: preString = "atan("; break; - - case EOpExp: preString = "exp("; break; - case EOpLog: preString = "log("; break; - case EOpExp2: preString = "exp2("; break; - case EOpLog2: preString = "log2("; break; - case EOpSqrt: preString = "sqrt("; break; - case EOpInverseSqrt: preString = "inversesqrt("; break; - - case EOpAbs: preString = "abs("; break; - case EOpSign: preString = "sign("; break; - case EOpFloor: preString = "floor("; break; - case EOpCeil: preString = "ceil("; break; - case EOpFract: preString = "fract("; break; - - case EOpLength: preString = "length("; break; - case EOpNormalize: preString = "normalize("; break; - - case EOpDFdx: preString = "dFdx("; break; - case EOpDFdy: preString = "dFdy("; break; - case EOpFwidth: preString = "fwidth("; break; - - case EOpAny: preString = "any("; break; - case EOpAll: preString = "all("; break; - - default: UNREACHABLE(); break; - } - - if (visit == PreVisit && node->getUseEmulatedFunction()) - preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString); - writeTriplet(visit, preString.c_str(), NULL, postString.c_str()); - - return true; -} - -bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection* node) -{ - TInfoSinkBase& out = objSink(); - - if (node->usesTernaryOperator()) - { - // Notice two brackets at the beginning and end. The outer ones - // encapsulate the whole ternary expression. This preserves the - // order of precedence when ternary expressions are used in a - // compound expression, i.e., c = 2 * (a < b ? 1 : 2). - out << "(("; - node->getCondition()->traverse(this); - out << ") ? ("; - node->getTrueBlock()->traverse(this); - out << ") : ("; - node->getFalseBlock()->traverse(this); - out << "))"; - } - else - { - out << "if ("; - node->getCondition()->traverse(this); - out << ")\n"; - - incrementDepth(); - visitCodeBlock(node->getTrueBlock()); - - if (node->getFalseBlock()) - { - out << "else\n"; - visitCodeBlock(node->getFalseBlock()); - } - decrementDepth(); - } - return false; -} - -bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) -{ - bool visitChildren = true; - TInfoSinkBase& out = objSink(); - TString preString; - bool delayedWrite = false; - switch (node->getOp()) - { - case EOpSequence: { - // Scope the sequences except when at the global scope. - if (depth > 0) out << "{\n"; - - incrementDepth(); - const TIntermSequence& sequence = node->getSequence(); - for (TIntermSequence::const_iterator iter = sequence.begin(); - iter != sequence.end(); ++iter) - { - TIntermNode* node = *iter; - ASSERT(node != NULL); - node->traverse(this); - - if (isSingleStatement(node)) - out << ";\n"; - } - decrementDepth(); - - // Scope the sequences except when at the global scope. - if (depth > 0) out << "}\n"; - visitChildren = false; - break; - } - case EOpPrototype: { - // Function declaration. - ASSERT(visit == PreVisit); - writeVariableType(node->getType()); - out << " " << hashName(node->getName()); - - out << "("; - writeFunctionParameters(node->getSequence()); - out << ")"; - - visitChildren = false; - break; - } - case EOpFunction: { - // Function definition. - ASSERT(visit == PreVisit); - writeVariableType(node->getType()); - out << " " << hashFunctionName(node->getName()); - - incrementDepth(); - // Function definition node contains one or two children nodes - // representing function parameters and function body. The latter - // is not present in case of empty function bodies. - const TIntermSequence& sequence = node->getSequence(); - ASSERT((sequence.size() == 1) || (sequence.size() == 2)); - TIntermSequence::const_iterator seqIter = sequence.begin(); - - // Traverse function parameters. - TIntermAggregate* params = (*seqIter)->getAsAggregate(); - ASSERT(params != NULL); - ASSERT(params->getOp() == EOpParameters); - params->traverse(this); - - // Traverse function body. - TIntermAggregate* body = ++seqIter != sequence.end() ? - (*seqIter)->getAsAggregate() : NULL; - visitCodeBlock(body); - decrementDepth(); - - // Fully processed; no need to visit children. - visitChildren = false; - break; - } - case EOpFunctionCall: - // Function call. - if (visit == PreVisit) - { - out << hashFunctionName(node->getName()) << "("; - } - else if (visit == InVisit) - { - out << ", "; - } - else - { - out << ")"; - } - break; - case EOpParameters: { - // Function parameters. - ASSERT(visit == PreVisit); - out << "("; - writeFunctionParameters(node->getSequence()); - out << ")"; - visitChildren = false; - break; - } - case EOpDeclaration: { - // Variable declaration. - if (visit == PreVisit) - { - const TIntermSequence& sequence = node->getSequence(); - const TIntermTyped* variable = sequence.front()->getAsTyped(); - writeVariableType(variable->getType()); - out << " "; - mDeclaringVariables = true; - } - else if (visit == InVisit) - { - out << ", "; - mDeclaringVariables = true; - } - else - { - mDeclaringVariables = false; - } - break; - } - case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break; - case EOpConstructVec2: writeTriplet(visit, "vec2(", ", ", ")"); break; - case EOpConstructVec3: writeTriplet(visit, "vec3(", ", ", ")"); break; - case EOpConstructVec4: writeTriplet(visit, "vec4(", ", ", ")"); break; - case EOpConstructBool: writeTriplet(visit, "bool(", NULL, ")"); break; - case EOpConstructBVec2: writeTriplet(visit, "bvec2(", ", ", ")"); break; - case EOpConstructBVec3: writeTriplet(visit, "bvec3(", ", ", ")"); break; - case EOpConstructBVec4: writeTriplet(visit, "bvec4(", ", ", ")"); break; - case EOpConstructInt: writeTriplet(visit, "int(", NULL, ")"); break; - case EOpConstructIVec2: writeTriplet(visit, "ivec2(", ", ", ")"); break; - case EOpConstructIVec3: writeTriplet(visit, "ivec3(", ", ", ")"); break; - case EOpConstructIVec4: writeTriplet(visit, "ivec4(", ", ", ")"); break; - case EOpConstructMat2: writeTriplet(visit, "mat2(", ", ", ")"); break; - case EOpConstructMat3: writeTriplet(visit, "mat3(", ", ", ")"); break; - case EOpConstructMat4: writeTriplet(visit, "mat4(", ", ", ")"); break; - case EOpConstructStruct: - if (visit == PreVisit) - { - const TType& type = node->getType(); - ASSERT(type.getBasicType() == EbtStruct); - out << hashName(type.getStruct()->name()) << "("; - } - else if (visit == InVisit) - { - out << ", "; - } - else - { - out << ")"; - } - break; - - case EOpLessThan: preString = "lessThan("; delayedWrite = true; break; - case EOpGreaterThan: preString = "greaterThan("; delayedWrite = true; break; - case EOpLessThanEqual: preString = "lessThanEqual("; delayedWrite = true; break; - case EOpGreaterThanEqual: preString = "greaterThanEqual("; delayedWrite = true; break; - case EOpVectorEqual: preString = "equal("; delayedWrite = true; break; - case EOpVectorNotEqual: preString = "notEqual("; delayedWrite = true; break; - case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break; - - case EOpMod: preString = "mod("; delayedWrite = true; break; - case EOpPow: preString = "pow("; delayedWrite = true; break; - case EOpAtan: preString = "atan("; delayedWrite = true; break; - case EOpMin: preString = "min("; delayedWrite = true; break; - case EOpMax: preString = "max("; delayedWrite = true; break; - case EOpClamp: preString = "clamp("; delayedWrite = true; break; - case EOpMix: preString = "mix("; delayedWrite = true; break; - case EOpStep: preString = "step("; delayedWrite = true; break; - case EOpSmoothStep: preString = "smoothstep("; delayedWrite = true; break; - - case EOpDistance: preString = "distance("; delayedWrite = true; break; - case EOpDot: preString = "dot("; delayedWrite = true; break; - case EOpCross: preString = "cross("; delayedWrite = true; break; - case EOpFaceForward: preString = "faceforward("; delayedWrite = true; break; - case EOpReflect: preString = "reflect("; delayedWrite = true; break; - case EOpRefract: preString = "refract("; delayedWrite = true; break; - case EOpMul: preString = "matrixCompMult("; delayedWrite = true; break; - - default: UNREACHABLE(); break; - } - if (delayedWrite && visit == PreVisit && node->getUseEmulatedFunction()) - preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString); - if (delayedWrite) - writeTriplet(visit, preString.c_str(), ", ", ")"); - return visitChildren; -} - -bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node) -{ - TInfoSinkBase& out = objSink(); - - incrementDepth(); - // Loop header. - TLoopType loopType = node->getType(); - if (loopType == ELoopFor) // for loop - { - if (!node->getUnrollFlag()) { - out << "for ("; - if (node->getInit()) - node->getInit()->traverse(this); - out << "; "; - - if (node->getCondition()) - node->getCondition()->traverse(this); - out << "; "; - - if (node->getExpression()) - node->getExpression()->traverse(this); - out << ")\n"; - } - } - else if (loopType == ELoopWhile) // while loop - { - out << "while ("; - ASSERT(node->getCondition() != NULL); - node->getCondition()->traverse(this); - out << ")\n"; - } - else // do-while loop - { - ASSERT(loopType == ELoopDoWhile); - out << "do\n"; - } - - // Loop body. - if (node->getUnrollFlag()) - { - TLoopIndexInfo indexInfo; - mLoopUnroll.FillLoopIndexInfo(node, indexInfo); - mLoopUnroll.Push(indexInfo); - while (mLoopUnroll.SatisfiesLoopCondition()) - { - visitCodeBlock(node->getBody()); - mLoopUnroll.Step(); - } - mLoopUnroll.Pop(); - } - else - { - visitCodeBlock(node->getBody()); - } - - // Loop footer. - if (loopType == ELoopDoWhile) // do-while loop - { - out << "while ("; - ASSERT(node->getCondition() != NULL); - node->getCondition()->traverse(this); - out << ");\n"; - } - decrementDepth(); - - // No need to visit children. They have been already processed in - // this function. - return false; -} - -bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch* node) -{ - switch (node->getFlowOp()) - { - case EOpKill: writeTriplet(visit, "discard", NULL, NULL); break; - case EOpBreak: writeTriplet(visit, "break", NULL, NULL); break; - case EOpContinue: writeTriplet(visit, "continue", NULL, NULL); break; - case EOpReturn: writeTriplet(visit, "return ", NULL, NULL); break; - default: UNREACHABLE(); break; - } - - return true; -} - -void TOutputGLSLBase::visitCodeBlock(TIntermNode* node) { - TInfoSinkBase &out = objSink(); - if (node != NULL) - { - node->traverse(this); - // Single statements not part of a sequence need to be terminated - // with semi-colon. - if (isSingleStatement(node)) - out << ";\n"; - } - else - { - out << "{\n}\n"; // Empty code block. - } -} - -TString TOutputGLSLBase::getTypeName(const TType& type) -{ - TInfoSinkBase out; - if (type.isMatrix()) - { - out << "mat"; - out << type.getNominalSize(); - } - else if (type.isVector()) - { - switch (type.getBasicType()) - { - case EbtFloat: out << "vec"; break; - case EbtInt: out << "ivec"; break; - case EbtBool: out << "bvec"; break; - default: UNREACHABLE(); break; - } - out << type.getNominalSize(); - } - else - { - if (type.getBasicType() == EbtStruct) - out << hashName(type.getStruct()->name()); - else - out << type.getBasicString(); - } - return TString(out.c_str()); -} - -TString TOutputGLSLBase::hashName(const TString& name) -{ - if (mHashFunction == NULL || name.empty()) - return name; - NameMap::const_iterator it = mNameMap.find(name.c_str()); - if (it != mNameMap.end()) - return it->second.c_str(); - TString hashedName = TIntermTraverser::hash(name, mHashFunction); - mNameMap[name.c_str()] = hashedName.c_str(); - return hashedName; -} - -TString TOutputGLSLBase::hashVariableName(const TString& name) -{ - if (mSymbolTable.findBuiltIn(name) != NULL) - return name; - return hashName(name); -} - -TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name) -{ - TString name = TFunction::unmangleName(mangled_name); - if (mSymbolTable.findBuiltIn(mangled_name) != NULL || name == "main") - return name; - return hashName(name); -} - -bool TOutputGLSLBase::structDeclared(const TStructure* structure) const -{ - return mDeclaredStructs.find(structure->name()) != mDeclaredStructs.end(); -} - -void TOutputGLSLBase::declareStruct(const TStructure* structure) -{ - TInfoSinkBase& out = objSink(); - - out << "struct " << hashName(structure->name()) << "{\n"; - const TFieldList& fields = structure->fields(); - for (size_t i = 0; i < fields.size(); ++i) - { - const TField* field = fields[i]; - if (writeVariablePrecision(field->type()->getPrecision())) - out << " "; - out << getTypeName(*field->type()) << " " << hashName(field->name()); - if (field->type()->isArray()) - out << arrayBrackets(*field->type()); - out << ";\n"; - } - out << "}"; - - mDeclaredStructs.insert(structure->name()); -} diff --git a/src/3rdparty/angle/src/compiler/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/OutputGLSLBase.h deleted file mode 100644 index df4ad68c2c..0000000000 --- a/src/3rdparty/angle/src/compiler/OutputGLSLBase.h +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ -#define CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ - -#include - -#include "compiler/ForLoopUnroll.h" -#include "compiler/intermediate.h" -#include "compiler/ParseHelper.h" - -class TOutputGLSLBase : public TIntermTraverser -{ -public: - TOutputGLSLBase(TInfoSinkBase& objSink, - ShArrayIndexClampingStrategy clampingStrategy, - ShHashFunction64 hashFunction, - NameMap& nameMap, - TSymbolTable& symbolTable); - -protected: - TInfoSinkBase& objSink() { return mObjSink; } - void writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr); - void writeVariableType(const TType& type); - virtual bool writeVariablePrecision(TPrecision precision) = 0; - void writeFunctionParameters(const TIntermSequence& args); - const ConstantUnion* writeConstantUnion(const TType& type, const ConstantUnion* pConstUnion); - TString getTypeName(const TType& type); - - virtual void visitSymbol(TIntermSymbol* node); - virtual void visitConstantUnion(TIntermConstantUnion* node); - virtual bool visitBinary(Visit visit, TIntermBinary* node); - virtual bool visitUnary(Visit visit, TIntermUnary* node); - virtual bool visitSelection(Visit visit, TIntermSelection* node); - virtual bool visitAggregate(Visit visit, TIntermAggregate* node); - virtual bool visitLoop(Visit visit, TIntermLoop* node); - virtual bool visitBranch(Visit visit, TIntermBranch* node); - - void visitCodeBlock(TIntermNode* node); - - - // Return the original name if hash function pointer is NULL; - // otherwise return the hashed name. - TString hashName(const TString& name); - // Same as hashName(), but without hashing built-in variables. - TString hashVariableName(const TString& name); - // Same as hashName(), but without hashing built-in functions. - TString hashFunctionName(const TString& mangled_name); - -private: - bool structDeclared(const TStructure* structure) const; - void declareStruct(const TStructure* structure); - - TInfoSinkBase& mObjSink; - bool mDeclaringVariables; - - // Structs are declared as the tree is traversed. This set contains all - // the structs already declared. It is maintained so that a struct is - // declared only once. - typedef std::set DeclaredStructs; - DeclaredStructs mDeclaredStructs; - - ForLoopUnroll mLoopUnroll; - - ShArrayIndexClampingStrategy mClampingStrategy; - - // name hashing. - ShHashFunction64 mHashFunction; - - NameMap& mNameMap; - - TSymbolTable& mSymbolTable; -}; - -#endif // CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ diff --git a/src/3rdparty/angle/src/compiler/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/OutputHLSL.cpp deleted file mode 100644 index 79a373ebab..0000000000 --- a/src/3rdparty/angle/src/compiler/OutputHLSL.cpp +++ /dev/null @@ -1,3094 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/OutputHLSL.h" - -#include "common/angleutils.h" -#include "compiler/debug.h" -#include "compiler/DetectDiscontinuity.h" -#include "compiler/InfoSink.h" -#include "compiler/SearchSymbol.h" -#include "compiler/UnfoldShortCircuit.h" - -#include -#include -#include - -namespace sh -{ -// Integer to TString conversion -TString str(int i) -{ - char buffer[20]; - snprintf(buffer, sizeof(buffer), "%d", i); - return buffer; -} - -OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType) - : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType) -{ - mUnfoldShortCircuit = new UnfoldShortCircuit(context, this); - mInsideFunction = false; - - mUsesTexture2D = false; - mUsesTexture2D_bias = false; - mUsesTexture2DProj = false; - mUsesTexture2DProj_bias = false; - mUsesTexture2DProjLod = false; - mUsesTexture2DLod = false; - mUsesTextureCube = false; - mUsesTextureCube_bias = false; - mUsesTextureCubeLod = false; - mUsesTexture2DLod0 = false; - mUsesTexture2DLod0_bias = false; - mUsesTexture2DProjLod0 = false; - mUsesTexture2DProjLod0_bias = false; - mUsesTextureCubeLod0 = false; - mUsesTextureCubeLod0_bias = false; - mUsesFragColor = false; - mUsesFragData = false; - mUsesDepthRange = false; - mUsesFragCoord = false; - mUsesPointCoord = false; - mUsesFrontFacing = false; - mUsesPointSize = false; - mUsesFragDepth = false; - mUsesXor = false; - mUsesMod1 = false; - mUsesMod2v = false; - mUsesMod2f = false; - mUsesMod3v = false; - mUsesMod3f = false; - mUsesMod4v = false; - mUsesMod4f = false; - mUsesFaceforward1 = false; - mUsesFaceforward2 = false; - mUsesFaceforward3 = false; - mUsesFaceforward4 = false; - mUsesAtan2_1 = false; - mUsesAtan2_2 = false; - mUsesAtan2_3 = false; - mUsesAtan2_4 = false; - - mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; - - mScopeDepth = 0; - - mUniqueIndex = 0; - - mContainsLoopDiscontinuity = false; - mOutputLod0Function = false; - mInsideDiscontinuousLoop = false; - - mExcessiveLoopIndex = NULL; - - if (mOutputType == SH_HLSL9_OUTPUT) - { - if (mContext.shaderType == SH_FRAGMENT_SHADER) - { - mUniformRegister = 3; // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront - } - else - { - mUniformRegister = 2; // Reserve registers for dx_DepthRange and dx_ViewAdjust - } - } - else - { - mUniformRegister = 0; - } - - mSamplerRegister = 0; -} - -OutputHLSL::~OutputHLSL() -{ - delete mUnfoldShortCircuit; -} - -void OutputHLSL::output() -{ - mContainsLoopDiscontinuity = mContext.shaderType == SH_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot); - - mContext.treeRoot->traverse(this); // Output the body first to determine what has to go in the header - header(); - - mContext.infoSink().obj << mHeader.c_str(); - mContext.infoSink().obj << mBody.c_str(); -} - -TInfoSinkBase &OutputHLSL::getBodyStream() -{ - return mBody; -} - -const ActiveUniforms &OutputHLSL::getUniforms() -{ - return mActiveUniforms; -} - -int OutputHLSL::vectorSize(const TType &type) const -{ - int elementSize = type.isMatrix() ? type.getNominalSize() : 1; - int arraySize = type.isArray() ? type.getArraySize() : 1; - - return elementSize * arraySize; -} - -void OutputHLSL::header() -{ - ShShaderType shaderType = mContext.shaderType; - TInfoSinkBase &out = mHeader; - - for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++) - { - out << *structDeclaration; - } - - for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++) - { - out << *constructor; - } - - TString uniforms; - TString varyings; - TString attributes; - - for (ReferencedSymbols::const_iterator uniform = mReferencedUniforms.begin(); uniform != mReferencedUniforms.end(); uniform++) - { - const TType &type = uniform->second->getType(); - const TString &name = uniform->second->getSymbol(); - - if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) // Also declare the texture - { - int index = samplerRegister(mReferencedUniforms[name]); - - uniforms += "uniform SamplerState sampler_" + decorateUniform(name, type) + arrayString(type) + - " : register(s" + str(index) + ");\n"; - - uniforms += "uniform " + textureString(type) + " texture_" + decorateUniform(name, type) + arrayString(type) + - " : register(t" + str(index) + ");\n"; - } - else - { - uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) + - " : register(" + registerString(mReferencedUniforms[name]) + ");\n"; - } - } - - for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); varying != mReferencedVaryings.end(); varying++) - { - const TType &type = varying->second->getType(); - const TString &name = varying->second->getSymbol(); - - // Program linking depends on this exact format - varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; - } - - for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); attribute != mReferencedAttributes.end(); attribute++) - { - const TType &type = attribute->second->getType(); - const TString &name = attribute->second->getSymbol(); - - attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; - } - - if (shaderType == SH_FRAGMENT_SHADER) - { - TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers"); - const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire)); - - const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1; - - out << "// Varyings\n"; - out << varyings; - out << "\n" - "static float4 gl_Color[" << numColorValues << "] =\n" - "{\n"; - for (unsigned int i = 0; i < numColorValues; i++) - { - out << " float4(0, 0, 0, 0)"; - if (i + 1 != numColorValues) - { - out << ","; - } - out << "\n"; - } - out << "};\n"; - - if (mUsesFragDepth) - { - out << "static float gl_Depth = 0.0;\n"; - } - - if (mUsesFragCoord) - { - out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n"; - } - - if (mUsesPointCoord) - { - out << "static float2 gl_PointCoord = float2(0.5, 0.5);\n"; - } - - if (mUsesFrontFacing) - { - out << "static bool gl_FrontFacing = false;\n"; - } - - out << "\n"; - - if (mUsesDepthRange) - { - out << "struct gl_DepthRangeParameters\n" - "{\n" - " float near;\n" - " float far;\n" - " float diff;\n" - "};\n" - "\n"; - } - - if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "cbuffer DriverConstants : register(b1)\n" - "{\n"; - - if (mUsesDepthRange) - { - out << " float3 dx_DepthRange : packoffset(c0);\n"; - } - - if (mUsesFragCoord) - { - out << " float4 dx_ViewCoords : packoffset(c1);\n"; - } - - if (mUsesFragCoord || mUsesFrontFacing) - { - out << " float3 dx_DepthFront : packoffset(c2);\n"; - } - - out << "};\n"; - } - else - { - if (mUsesDepthRange) - { - out << "uniform float3 dx_DepthRange : register(c0);"; - } - - if (mUsesFragCoord) - { - out << "uniform float4 dx_ViewCoords : register(c1);\n"; - } - - if (mUsesFragCoord || mUsesFrontFacing) - { - out << "uniform float3 dx_DepthFront : register(c2);\n"; - } - } - - out << "\n"; - - if (mUsesDepthRange) - { - out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" - "\n"; - } - - out << uniforms; - out << "\n"; - - if (mUsesTexture2D) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2D(sampler2D s, float2 t)\n" - "{\n" - " return tex2D(s, t);\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n" - "{\n" - " return t.Sample(s, uv);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - - if (mUsesTexture2D_bias) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n" - "{\n" - " return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv, float bias)\n" - "{\n" - " return t.SampleBias(s, uv, bias);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - - if (mUsesTexture2DProj) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n" - "{\n" - " return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n" - "}\n" - "\n" - "float4 gl_texture2DProj(sampler2D s, float4 t)\n" - "{\n" - " return tex2Dproj(s, t);\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n" - "{\n" - " return t.Sample(s, float2(uvw.x / uvw.z, uvw.y / uvw.z));\n" - "}\n" - "\n" - "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n" - "{\n" - " return t.Sample(s, float2(uvw.x / uvw.w, uvw.y / uvw.w));\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - - if (mUsesTexture2DProj_bias) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2DProj(sampler2D s, float3 t, float bias)\n" - "{\n" - " return tex2Dbias(s, float4(t.x / t.z, t.y / t.z, 0, bias));\n" - "}\n" - "\n" - "float4 gl_texture2DProj(sampler2D s, float4 t, float bias)\n" - "{\n" - " return tex2Dbias(s, float4(t.x / t.w, t.y / t.w, 0, bias));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw, float bias)\n" - "{\n" - " return t.SampleBias(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), bias);\n" - "}\n" - "\n" - "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw, float bias)\n" - "{\n" - " return t.SampleBias(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), bias);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - - if (mUsesTextureCube) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" - "{\n" - " return texCUBE(s, t);\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n" - "{\n" - " return t.Sample(s, uvw);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - - if (mUsesTextureCube_bias) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_textureCube(samplerCUBE s, float3 t, float bias)\n" - "{\n" - " return texCUBEbias(s, float4(t.x, t.y, t.z, bias));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw, float bias)\n" - "{\n" - " return t.SampleBias(s, uvw, bias);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - - // These *Lod0 intrinsics are not available in GL fragment shaders. - // They are used to sample using discontinuous texture coordinates. - if (mUsesTexture2DLod0) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2DLod0(sampler2D s, float2 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv)\n" - "{\n" - " return t.SampleLevel(s, uv, 0);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - - if (mUsesTexture2DLod0_bias) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2DLod0(sampler2D s, float2 t, float bias)\n" - "{\n" - " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv, float bias)\n" - "{\n" - " return t.SampleLevel(s, uv, 0);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - - if (mUsesTexture2DProjLod0) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2DProjLod0(sampler2D s, float3 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" - "}\n" - "\n" - "float4 gl_texture2DProjLod(sampler2D s, float4 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float3 uvw)\n" - "{\n" - " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n" - "}\n" - "\n" - "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float4 uvw)\n" - "{\n" - " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - - if (mUsesTexture2DProjLod0_bias) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2DProjLod0_bias(sampler2D s, float3 t, float bias)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" - "}\n" - "\n" - "float4 gl_texture2DProjLod_bias(sampler2D s, float4 t, float bias)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float3 uvw, float bias)\n" - "{\n" - " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n" - "}\n" - "\n" - "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float4 uvw, float bias)\n" - "{\n" - " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - - if (mUsesTextureCubeLod0) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t)\n" - "{\n" - " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw)\n" - "{\n" - " return t.SampleLevel(s, uvw, 0);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - - if (mUsesTextureCubeLod0_bias) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t, float bias)\n" - "{\n" - " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw, float bias)\n" - "{\n" - " return t.SampleLevel(s, uvw, 0);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - - if (usingMRTExtension && mNumRenderTargets > 1) - { - out << "#define GL_USES_MRT\n"; - } - - if (mUsesFragColor) - { - out << "#define GL_USES_FRAG_COLOR\n"; - } - - if (mUsesFragData) - { - out << "#define GL_USES_FRAG_DATA\n"; - } - } - else // Vertex shader - { - out << "// Attributes\n"; - out << attributes; - out << "\n" - "static float4 gl_Position = float4(0, 0, 0, 0);\n"; - - if (mUsesPointSize) - { - out << "static float gl_PointSize = float(1);\n"; - } - - out << "\n" - "// Varyings\n"; - out << varyings; - out << "\n"; - - if (mUsesDepthRange) - { - out << "struct gl_DepthRangeParameters\n" - "{\n" - " float near;\n" - " float far;\n" - " float diff;\n" - "};\n" - "\n"; - } - - if (mOutputType == SH_HLSL11_OUTPUT) - { - if (mUsesDepthRange) - { - out << "cbuffer DriverConstants : register(b1)\n" - "{\n" - " float3 dx_DepthRange : packoffset(c0);\n" - "};\n" - "\n"; - } - } - else - { - if (mUsesDepthRange) - { - out << "uniform float3 dx_DepthRange : register(c0);\n"; - } - - out << "uniform float4 dx_ViewAdjust : register(c1);\n" - "\n"; - } - - if (mUsesDepthRange) - { - out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" - "\n"; - } - - out << uniforms; - out << "\n"; - - if (mUsesTexture2D) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2D(sampler2D s, float2 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n" - "{\n" - " return t.SampleLevel(s, uv, 0);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - - if (mUsesTexture2DLod) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2DLod(sampler2D s, float2 t, float lod)\n" - "{\n" - " return tex2Dlod(s, float4(t.x, t.y, 0, lod));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2DLod(Texture2D t, SamplerState s, float2 uv, float lod)\n" - "{\n" - " return t.SampleLevel(s, uv, lod);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - - if (mUsesTexture2DProj) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" - "}\n" - "\n" - "float4 gl_texture2DProj(sampler2D s, float4 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n" - "{\n" - " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n" - "}\n" - "\n" - "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n" - "{\n" - " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - - if (mUsesTexture2DProjLod) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2DProjLod(sampler2D s, float3 t, float lod)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, lod));\n" - "}\n" - "\n" - "float4 gl_texture2DProjLod(sampler2D s, float4 t, float lod)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, lod));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw, float lod)\n" - "{\n" - " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), lod);\n" - "}\n" - "\n" - "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n" - "{\n" - " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), lod);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - - if (mUsesTextureCube) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" - "{\n" - " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n" - "{\n" - " return t.SampleLevel(s, uvw, 0);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - - if (mUsesTextureCubeLod) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_textureCubeLod(samplerCUBE s, float3 t, float lod)\n" - "{\n" - " return texCUBElod(s, float4(t.x, t.y, t.z, lod));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_textureCubeLod(TextureCube t, SamplerState s, float3 uvw, float lod)\n" - "{\n" - " return t.SampleLevel(s, uvw, lod);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } - } - - if (mUsesFragCoord) - { - out << "#define GL_USES_FRAG_COORD\n"; - } - - if (mUsesPointCoord) - { - out << "#define GL_USES_POINT_COORD\n"; - } - - if (mUsesFrontFacing) - { - out << "#define GL_USES_FRONT_FACING\n"; - } - - if (mUsesPointSize) - { - out << "#define GL_USES_POINT_SIZE\n"; - } - - if (mUsesFragDepth) - { - out << "#define GL_USES_FRAG_DEPTH\n"; - } - - if (mUsesDepthRange) - { - out << "#define GL_USES_DEPTH_RANGE\n"; - } - - if (mUsesXor) - { - out << "bool xor(bool p, bool q)\n" - "{\n" - " return (p || q) && !(p && q);\n" - "}\n" - "\n"; - } - - if (mUsesMod1) - { - out << "float mod(float x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod2v) - { - out << "float2 mod(float2 x, float2 y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod2f) - { - out << "float2 mod(float2 x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod3v) - { - out << "float3 mod(float3 x, float3 y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod3f) - { - out << "float3 mod(float3 x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod4v) - { - out << "float4 mod(float4 x, float4 y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod4f) - { - out << "float4 mod(float4 x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesFaceforward1) - { - out << "float faceforward(float N, float I, float Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n" - "\n"; - } - - if (mUsesFaceforward2) - { - out << "float2 faceforward(float2 N, float2 I, float2 Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n" - "\n"; - } - - if (mUsesFaceforward3) - { - out << "float3 faceforward(float3 N, float3 I, float3 Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n" - "\n"; - } - - if (mUsesFaceforward4) - { - out << "float4 faceforward(float4 N, float4 I, float4 Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n" - "\n"; - } - - if (mUsesAtan2_1) - { - out << "float atanyx(float y, float x)\n" - "{\n" - " if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN - " return atan2(y, x);\n" - "}\n"; - } - - if (mUsesAtan2_2) - { - out << "float2 atanyx(float2 y, float2 x)\n" - "{\n" - " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" - " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" - " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n" - "}\n"; - } - - if (mUsesAtan2_3) - { - out << "float3 atanyx(float3 y, float3 x)\n" - "{\n" - " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" - " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" - " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" - " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n" - "}\n"; - } - - if (mUsesAtan2_4) - { - out << "float4 atanyx(float4 y, float4 x)\n" - "{\n" - " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" - " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" - " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" - " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n" - " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n" - "}\n"; - } -} - -void OutputHLSL::visitSymbol(TIntermSymbol *node) -{ - TInfoSinkBase &out = mBody; - - TString name = node->getSymbol(); - - if (name == "gl_FragColor") - { - out << "gl_Color[0]"; - mUsesFragColor = true; - } - else if (name == "gl_FragData") - { - out << "gl_Color"; - mUsesFragData = true; - } - else if (name == "gl_DepthRange") - { - mUsesDepthRange = true; - out << name; - } - else if (name == "gl_FragCoord") - { - mUsesFragCoord = true; - out << name; - } - else if (name == "gl_PointCoord") - { - mUsesPointCoord = true; - out << name; - } - else if (name == "gl_FrontFacing") - { - mUsesFrontFacing = true; - out << name; - } - else if (name == "gl_PointSize") - { - mUsesPointSize = true; - out << name; - } - else if (name == "gl_FragDepthEXT") - { - mUsesFragDepth = true; - out << "gl_Depth"; - } - else - { - TQualifier qualifier = node->getQualifier(); - - if (qualifier == EvqUniform) - { - mReferencedUniforms[name] = node; - out << decorateUniform(name, node->getType()); - } - else if (qualifier == EvqAttribute) - { - mReferencedAttributes[name] = node; - out << decorate(name); - } - else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut || qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn) - { - mReferencedVaryings[name] = node; - out << decorate(name); - } - else - { - out << decorate(name); - } - } -} - -bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) -{ - TInfoSinkBase &out = mBody; - - switch (node->getOp()) - { - case EOpAssign: outputTriplet(visit, "(", " = ", ")"); break; - case EOpInitialize: - if (visit == PreVisit) - { - // GLSL allows to write things like "float x = x;" where a new variable x is defined - // and the value of an existing variable x is assigned. HLSL uses C semantics (the - // new variable is created before the assignment is evaluated), so we need to convert - // this to "float t = x, x = t;". - - TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode(); - TIntermTyped *expression = node->getRight(); - - sh::SearchSymbol searchSymbol(symbolNode->getSymbol()); - expression->traverse(&searchSymbol); - bool sameSymbol = searchSymbol.foundMatch(); - - if (sameSymbol) - { - // Type already printed - out << "t" + str(mUniqueIndex) + " = "; - expression->traverse(this); - out << ", "; - symbolNode->traverse(this); - out << " = t" + str(mUniqueIndex); - - mUniqueIndex++; - return false; - } - } - else if (visit == InVisit) - { - out << " = "; - } - break; - case EOpAddAssign: outputTriplet(visit, "(", " += ", ")"); break; - case EOpSubAssign: outputTriplet(visit, "(", " -= ", ")"); break; - case EOpMulAssign: outputTriplet(visit, "(", " *= ", ")"); break; - case EOpVectorTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break; - case EOpMatrixTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break; - case EOpVectorTimesMatrixAssign: - if (visit == PreVisit) - { - out << "("; - } - else if (visit == InVisit) - { - out << " = mul("; - node->getLeft()->traverse(this); - out << ", transpose("; - } - else - { - out << ")))"; - } - break; - case EOpMatrixTimesMatrixAssign: - if (visit == PreVisit) - { - out << "("; - } - else if (visit == InVisit) - { - out << " = mul("; - node->getLeft()->traverse(this); - out << ", "; - } - else - { - out << "))"; - } - break; - case EOpDivAssign: outputTriplet(visit, "(", " /= ", ")"); break; - case EOpIndexDirect: outputTriplet(visit, "", "[", "]"); break; - case EOpIndexIndirect: outputTriplet(visit, "", "[", "]"); break; - case EOpIndexDirectStruct: - if (visit == InVisit) - { - const TStructure* structure = node->getLeft()->getType().getStruct(); - const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion(); - const TField* field = structure->fields()[index->getIConst(0)]; - out << "." + decorateField(field->name(), node->getLeft()->getType()); - - return false; - } - break; - case EOpVectorSwizzle: - if (visit == InVisit) - { - out << "."; - - TIntermAggregate *swizzle = node->getRight()->getAsAggregate(); - - if (swizzle) - { - TIntermSequence &sequence = swizzle->getSequence(); - - for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) - { - TIntermConstantUnion *element = (*sit)->getAsConstantUnion(); - - if (element) - { - int i = element->getIConst(0); - - switch (i) - { - case 0: out << "x"; break; - case 1: out << "y"; break; - case 2: out << "z"; break; - case 3: out << "w"; break; - default: UNREACHABLE(); - } - } - else UNREACHABLE(); - } - } - else UNREACHABLE(); - - return false; // Fully processed - } - break; - case EOpAdd: outputTriplet(visit, "(", " + ", ")"); break; - case EOpSub: outputTriplet(visit, "(", " - ", ")"); break; - case EOpMul: outputTriplet(visit, "(", " * ", ")"); break; - case EOpDiv: outputTriplet(visit, "(", " / ", ")"); break; - case EOpEqual: - case EOpNotEqual: - if (node->getLeft()->isScalar()) - { - if (node->getOp() == EOpEqual) - { - outputTriplet(visit, "(", " == ", ")"); - } - else - { - outputTriplet(visit, "(", " != ", ")"); - } - } - else if (node->getLeft()->getBasicType() == EbtStruct) - { - if (node->getOp() == EOpEqual) - { - out << "("; - } - else - { - out << "!("; - } - - const TFieldList &fields = node->getLeft()->getType().getStruct()->fields(); - - for (size_t i = 0; i < fields.size(); i++) - { - const TField *field = fields[i]; - - node->getLeft()->traverse(this); - out << "." + decorateField(field->name(), node->getLeft()->getType()) + " == "; - node->getRight()->traverse(this); - out << "." + decorateField(field->name(), node->getLeft()->getType()); - - if (i < fields.size() - 1) - { - out << " && "; - } - } - - out << ")"; - - return false; - } - else - { - ASSERT(node->getLeft()->isMatrix() || node->getLeft()->isVector()); - - if (node->getOp() == EOpEqual) - { - outputTriplet(visit, "all(", " == ", ")"); - } - else - { - outputTriplet(visit, "!all(", " == ", ")"); - } - } - break; - case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; - case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break; - case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break; - case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break; - case EOpVectorTimesScalar: outputTriplet(visit, "(", " * ", ")"); break; - case EOpMatrixTimesScalar: outputTriplet(visit, "(", " * ", ")"); break; - case EOpVectorTimesMatrix: outputTriplet(visit, "mul(", ", transpose(", "))"); break; - case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break; - case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break; - case EOpLogicalOr: - out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex(); - return false; - case EOpLogicalXor: - mUsesXor = true; - outputTriplet(visit, "xor(", ", ", ")"); - break; - case EOpLogicalAnd: - out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex(); - return false; - default: UNREACHABLE(); - } - - return true; -} - -bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) -{ - switch (node->getOp()) - { - case EOpNegative: outputTriplet(visit, "(-", "", ")"); break; - case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break; - case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break; - case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break; - case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break; - case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break; - case EOpPreDecrement: outputTriplet(visit, "(--", "", ")"); break; - case EOpConvIntToBool: - case EOpConvFloatToBool: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: outputTriplet(visit, "bool(", "", ")"); break; - case 2: outputTriplet(visit, "bool2(", "", ")"); break; - case 3: outputTriplet(visit, "bool3(", "", ")"); break; - case 4: outputTriplet(visit, "bool4(", "", ")"); break; - default: UNREACHABLE(); - } - break; - case EOpConvBoolToFloat: - case EOpConvIntToFloat: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: outputTriplet(visit, "float(", "", ")"); break; - case 2: outputTriplet(visit, "float2(", "", ")"); break; - case 3: outputTriplet(visit, "float3(", "", ")"); break; - case 4: outputTriplet(visit, "float4(", "", ")"); break; - default: UNREACHABLE(); - } - break; - case EOpConvFloatToInt: - case EOpConvBoolToInt: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: outputTriplet(visit, "int(", "", ")"); break; - case 2: outputTriplet(visit, "int2(", "", ")"); break; - case 3: outputTriplet(visit, "int3(", "", ")"); break; - case 4: outputTriplet(visit, "int4(", "", ")"); break; - default: UNREACHABLE(); - } - break; - case EOpRadians: outputTriplet(visit, "radians(", "", ")"); break; - case EOpDegrees: outputTriplet(visit, "degrees(", "", ")"); break; - case EOpSin: outputTriplet(visit, "sin(", "", ")"); break; - case EOpCos: outputTriplet(visit, "cos(", "", ")"); break; - case EOpTan: outputTriplet(visit, "tan(", "", ")"); break; - case EOpAsin: outputTriplet(visit, "asin(", "", ")"); break; - case EOpAcos: outputTriplet(visit, "acos(", "", ")"); break; - case EOpAtan: outputTriplet(visit, "atan(", "", ")"); break; - case EOpExp: outputTriplet(visit, "exp(", "", ")"); break; - case EOpLog: outputTriplet(visit, "log(", "", ")"); break; - case EOpExp2: outputTriplet(visit, "exp2(", "", ")"); break; - case EOpLog2: outputTriplet(visit, "log2(", "", ")"); break; - case EOpSqrt: outputTriplet(visit, "sqrt(", "", ")"); break; - case EOpInverseSqrt: outputTriplet(visit, "rsqrt(", "", ")"); break; - case EOpAbs: outputTriplet(visit, "abs(", "", ")"); break; - case EOpSign: outputTriplet(visit, "sign(", "", ")"); break; - case EOpFloor: outputTriplet(visit, "floor(", "", ")"); break; - case EOpCeil: outputTriplet(visit, "ceil(", "", ")"); break; - case EOpFract: outputTriplet(visit, "frac(", "", ")"); break; - case EOpLength: outputTriplet(visit, "length(", "", ")"); break; - case EOpNormalize: outputTriplet(visit, "normalize(", "", ")"); break; - case EOpDFdx: - if(mInsideDiscontinuousLoop || mOutputLod0Function) - { - outputTriplet(visit, "(", "", ", 0.0)"); - } - else - { - outputTriplet(visit, "ddx(", "", ")"); - } - break; - case EOpDFdy: - if(mInsideDiscontinuousLoop || mOutputLod0Function) - { - outputTriplet(visit, "(", "", ", 0.0)"); - } - else - { - outputTriplet(visit, "ddy(", "", ")"); - } - break; - case EOpFwidth: - if(mInsideDiscontinuousLoop || mOutputLod0Function) - { - outputTriplet(visit, "(", "", ", 0.0)"); - } - else - { - outputTriplet(visit, "fwidth(", "", ")"); - } - break; - case EOpAny: outputTriplet(visit, "any(", "", ")"); break; - case EOpAll: outputTriplet(visit, "all(", "", ")"); break; - default: UNREACHABLE(); - } - - return true; -} - -bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) -{ - TInfoSinkBase &out = mBody; - - switch (node->getOp()) - { - case EOpSequence: - { - if (mInsideFunction) - { - outputLineDirective(node->getLine().first_line); - out << "{\n"; - - mScopeDepth++; - - if (mScopeBracket.size() < mScopeDepth) - { - mScopeBracket.push_back(0); // New scope level - } - else - { - mScopeBracket[mScopeDepth - 1]++; // New scope at existing level - } - } - - for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++) - { - outputLineDirective((*sit)->getLine().first_line); - - traverseStatements(*sit); - - out << ";\n"; - } - - if (mInsideFunction) - { - outputLineDirective(node->getLine().last_line); - out << "}\n"; - - mScopeDepth--; - } - - return false; - } - case EOpDeclaration: - if (visit == PreVisit) - { - TIntermSequence &sequence = node->getSequence(); - TIntermTyped *variable = sequence[0]->getAsTyped(); - - if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal)) - { - if (variable->getType().getStruct()) - { - addConstructor(variable->getType(), scopedStruct(variable->getType().getStruct()->name()), NULL); - } - - if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration - { - if (!mInsideFunction) - { - out << "static "; - } - - out << typeString(variable->getType()) + " "; - - for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) - { - TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); - - if (symbol) - { - symbol->traverse(this); - out << arrayString(symbol->getType()); - out << " = " + initializer(variable->getType()); - } - else - { - (*sit)->traverse(this); - } - - if (*sit != sequence.back()) - { - out << ", "; - } - } - } - else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration - { - // Already added to constructor map - } - else UNREACHABLE(); - } - else if (variable && (variable->getQualifier() == EvqVaryingOut || variable->getQualifier() == EvqInvariantVaryingOut)) - { - for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) - { - TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); - - if (symbol) - { - // Vertex (output) varyings which are declared but not written to should still be declared to allow successful linking - mReferencedVaryings[symbol->getSymbol()] = symbol; - } - else - { - (*sit)->traverse(this); - } - } - } - - return false; - } - else if (visit == InVisit) - { - out << ", "; - } - break; - case EOpPrototype: - if (visit == PreVisit) - { - out << typeString(node->getType()) << " " << decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "("); - - TIntermSequence &arguments = node->getSequence(); - - for (unsigned int i = 0; i < arguments.size(); i++) - { - TIntermSymbol *symbol = arguments[i]->getAsSymbolNode(); - - if (symbol) - { - out << argumentString(symbol); - - if (i < arguments.size() - 1) - { - out << ", "; - } - } - else UNREACHABLE(); - } - - out << ");\n"; - - // Also prototype the Lod0 variant if needed - if (mContainsLoopDiscontinuity && !mOutputLod0Function) - { - mOutputLod0Function = true; - node->traverse(this); - mOutputLod0Function = false; - } - - return false; - } - break; - case EOpComma: outputTriplet(visit, "(", ", ", ")"); break; - case EOpFunction: - { - TString name = TFunction::unmangleName(node->getName()); - - out << typeString(node->getType()) << " "; - - if (name == "main") - { - out << "gl_main("; - } - else - { - out << decorate(name) << (mOutputLod0Function ? "Lod0(" : "("); - } - - TIntermSequence &sequence = node->getSequence(); - TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence(); - - for (unsigned int i = 0; i < arguments.size(); i++) - { - TIntermSymbol *symbol = arguments[i]->getAsSymbolNode(); - - if (symbol) - { - if (symbol->getType().getStruct()) - { - addConstructor(symbol->getType(), scopedStruct(symbol->getType().getStruct()->name()), NULL); - } - - out << argumentString(symbol); - - if (i < arguments.size() - 1) - { - out << ", "; - } - } - else UNREACHABLE(); - } - - out << ")\n" - "{\n"; - - if (sequence.size() > 1) - { - mInsideFunction = true; - sequence[1]->traverse(this); - mInsideFunction = false; - } - - out << "}\n"; - - if (mContainsLoopDiscontinuity && !mOutputLod0Function) - { - if (name != "main") - { - mOutputLod0Function = true; - node->traverse(this); - mOutputLod0Function = false; - } - } - - return false; - } - break; - case EOpFunctionCall: - { - TString name = TFunction::unmangleName(node->getName()); - bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function; - - if (node->isUserDefined()) - { - out << decorate(name) << (lod0 ? "Lod0(" : "("); - } - else - { - if (name == "texture2D") - { - if (!lod0) - { - if (node->getSequence().size() == 2) - { - mUsesTexture2D = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTexture2D_bias = true; - } - else UNREACHABLE(); - - out << "gl_texture2D("; - } - else - { - if (node->getSequence().size() == 2) - { - mUsesTexture2DLod0 = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTexture2DLod0_bias = true; - } - else UNREACHABLE(); - - out << "gl_texture2DLod0("; - } - } - else if (name == "texture2DProj") - { - if (!lod0) - { - if (node->getSequence().size() == 2) - { - mUsesTexture2DProj = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTexture2DProj_bias = true; - } - else UNREACHABLE(); - - out << "gl_texture2DProj("; - } - else - { - if (node->getSequence().size() == 2) - { - mUsesTexture2DProjLod0 = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTexture2DProjLod0_bias = true; - } - else UNREACHABLE(); - - out << "gl_texture2DProjLod0("; - } - } - else if (name == "textureCube") - { - if (!lod0) - { - if (node->getSequence().size() == 2) - { - mUsesTextureCube = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTextureCube_bias = true; - } - else UNREACHABLE(); - - out << "gl_textureCube("; - } - else - { - if (node->getSequence().size() == 2) - { - mUsesTextureCubeLod0 = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTextureCubeLod0_bias = true; - } - else UNREACHABLE(); - - out << "gl_textureCubeLod0("; - } - } - else if (name == "texture2DLod") - { - if (node->getSequence().size() == 3) - { - mUsesTexture2DLod = true; - } - else UNREACHABLE(); - - out << "gl_texture2DLod("; - } - else if (name == "texture2DProjLod") - { - if (node->getSequence().size() == 3) - { - mUsesTexture2DProjLod = true; - } - else UNREACHABLE(); - - out << "gl_texture2DProjLod("; - } - else if (name == "textureCubeLod") - { - if (node->getSequence().size() == 3) - { - mUsesTextureCubeLod = true; - } - else UNREACHABLE(); - - out << "gl_textureCubeLod("; - } - else UNREACHABLE(); - } - - TIntermSequence &arguments = node->getSequence(); - - for (TIntermSequence::iterator arg = arguments.begin(); arg != arguments.end(); arg++) - { - if (mOutputType == SH_HLSL11_OUTPUT && IsSampler((*arg)->getAsTyped()->getBasicType())) - { - out << "texture_"; - (*arg)->traverse(this); - out << ", sampler_"; - } - - (*arg)->traverse(this); - - if (arg < arguments.end() - 1) - { - out << ", "; - } - } - - out << ")"; - - return false; - } - break; - case EOpParameters: outputTriplet(visit, "(", ", ", ")\n{\n"); break; - case EOpConstructFloat: - addConstructor(node->getType(), "vec1", &node->getSequence()); - outputTriplet(visit, "vec1(", "", ")"); - break; - case EOpConstructVec2: - addConstructor(node->getType(), "vec2", &node->getSequence()); - outputTriplet(visit, "vec2(", ", ", ")"); - break; - case EOpConstructVec3: - addConstructor(node->getType(), "vec3", &node->getSequence()); - outputTriplet(visit, "vec3(", ", ", ")"); - break; - case EOpConstructVec4: - addConstructor(node->getType(), "vec4", &node->getSequence()); - outputTriplet(visit, "vec4(", ", ", ")"); - break; - case EOpConstructBool: - addConstructor(node->getType(), "bvec1", &node->getSequence()); - outputTriplet(visit, "bvec1(", "", ")"); - break; - case EOpConstructBVec2: - addConstructor(node->getType(), "bvec2", &node->getSequence()); - outputTriplet(visit, "bvec2(", ", ", ")"); - break; - case EOpConstructBVec3: - addConstructor(node->getType(), "bvec3", &node->getSequence()); - outputTriplet(visit, "bvec3(", ", ", ")"); - break; - case EOpConstructBVec4: - addConstructor(node->getType(), "bvec4", &node->getSequence()); - outputTriplet(visit, "bvec4(", ", ", ")"); - break; - case EOpConstructInt: - addConstructor(node->getType(), "ivec1", &node->getSequence()); - outputTriplet(visit, "ivec1(", "", ")"); - break; - case EOpConstructIVec2: - addConstructor(node->getType(), "ivec2", &node->getSequence()); - outputTriplet(visit, "ivec2(", ", ", ")"); - break; - case EOpConstructIVec3: - addConstructor(node->getType(), "ivec3", &node->getSequence()); - outputTriplet(visit, "ivec3(", ", ", ")"); - break; - case EOpConstructIVec4: - addConstructor(node->getType(), "ivec4", &node->getSequence()); - outputTriplet(visit, "ivec4(", ", ", ")"); - break; - case EOpConstructMat2: - addConstructor(node->getType(), "mat2", &node->getSequence()); - outputTriplet(visit, "mat2(", ", ", ")"); - break; - case EOpConstructMat3: - addConstructor(node->getType(), "mat3", &node->getSequence()); - outputTriplet(visit, "mat3(", ", ", ")"); - break; - case EOpConstructMat4: - addConstructor(node->getType(), "mat4", &node->getSequence()); - outputTriplet(visit, "mat4(", ", ", ")"); - break; - case EOpConstructStruct: - addConstructor(node->getType(), scopedStruct(node->getType().getStruct()->name()), &node->getSequence()); - outputTriplet(visit, structLookup(node->getType().getStruct()->name()) + "_ctor(", ", ", ")"); - break; - case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; - case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break; - case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break; - case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break; - case EOpVectorEqual: outputTriplet(visit, "(", " == ", ")"); break; - case EOpVectorNotEqual: outputTriplet(visit, "(", " != ", ")"); break; - case EOpMod: - { - // We need to look at the number of components in both arguments - switch (node->getSequence()[0]->getAsTyped()->getNominalSize() * 10 - + node->getSequence()[1]->getAsTyped()->getNominalSize()) - { - case 11: mUsesMod1 = true; break; - case 22: mUsesMod2v = true; break; - case 21: mUsesMod2f = true; break; - case 33: mUsesMod3v = true; break; - case 31: mUsesMod3f = true; break; - case 44: mUsesMod4v = true; break; - case 41: mUsesMod4f = true; break; - default: UNREACHABLE(); - } - - outputTriplet(visit, "mod(", ", ", ")"); - } - break; - case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break; - case EOpAtan: - ASSERT(node->getSequence().size() == 2); // atan(x) is a unary operator - switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) - { - case 1: mUsesAtan2_1 = true; break; - case 2: mUsesAtan2_2 = true; break; - case 3: mUsesAtan2_3 = true; break; - case 4: mUsesAtan2_4 = true; break; - default: UNREACHABLE(); - } - outputTriplet(visit, "atanyx(", ", ", ")"); - break; - case EOpMin: outputTriplet(visit, "min(", ", ", ")"); break; - case EOpMax: outputTriplet(visit, "max(", ", ", ")"); break; - case EOpClamp: outputTriplet(visit, "clamp(", ", ", ")"); break; - case EOpMix: outputTriplet(visit, "lerp(", ", ", ")"); break; - case EOpStep: outputTriplet(visit, "step(", ", ", ")"); break; - case EOpSmoothStep: outputTriplet(visit, "smoothstep(", ", ", ")"); break; - case EOpDistance: outputTriplet(visit, "distance(", ", ", ")"); break; - case EOpDot: outputTriplet(visit, "dot(", ", ", ")"); break; - case EOpCross: outputTriplet(visit, "cross(", ", ", ")"); break; - case EOpFaceForward: - { - switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) // Number of components in the first argument - { - case 1: mUsesFaceforward1 = true; break; - case 2: mUsesFaceforward2 = true; break; - case 3: mUsesFaceforward3 = true; break; - case 4: mUsesFaceforward4 = true; break; - default: UNREACHABLE(); - } - - outputTriplet(visit, "faceforward(", ", ", ")"); - } - break; - case EOpReflect: outputTriplet(visit, "reflect(", ", ", ")"); break; - case EOpRefract: outputTriplet(visit, "refract(", ", ", ")"); break; - case EOpMul: outputTriplet(visit, "(", " * ", ")"); break; - default: UNREACHABLE(); - } - - return true; -} - -bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) -{ - TInfoSinkBase &out = mBody; - - if (node->usesTernaryOperator()) - { - out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex(); - } - else // if/else statement - { - mUnfoldShortCircuit->traverse(node->getCondition()); - - out << "if("; - - node->getCondition()->traverse(this); - - out << ")\n"; - - outputLineDirective(node->getLine().first_line); - out << "{\n"; - - if (node->getTrueBlock()) - { - traverseStatements(node->getTrueBlock()); - } - - outputLineDirective(node->getLine().first_line); - out << ";\n}\n"; - - if (node->getFalseBlock()) - { - out << "else\n"; - - outputLineDirective(node->getFalseBlock()->getLine().first_line); - out << "{\n"; - - outputLineDirective(node->getFalseBlock()->getLine().first_line); - traverseStatements(node->getFalseBlock()); - - outputLineDirective(node->getFalseBlock()->getLine().first_line); - out << ";\n}\n"; - } - } - - return false; -} - -void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node) -{ - writeConstantUnion(node->getType(), node->getUnionArrayPointer()); -} - -bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) -{ - bool wasDiscontinuous = mInsideDiscontinuousLoop; - - if (mContainsLoopDiscontinuity && !mInsideDiscontinuousLoop) - { - mInsideDiscontinuousLoop = containsLoopDiscontinuity(node); - } - - if (mOutputType == SH_HLSL9_OUTPUT) - { - if (handleExcessiveLoop(node)) - { - return false; - } - } - - TInfoSinkBase &out = mBody; - - if (node->getType() == ELoopDoWhile) - { - out << "{do\n"; - - outputLineDirective(node->getLine().first_line); - out << "{\n"; - } - else - { - out << "{for("; - - if (node->getInit()) - { - node->getInit()->traverse(this); - } - - out << "; "; - - if (node->getCondition()) - { - node->getCondition()->traverse(this); - } - - out << "; "; - - if (node->getExpression()) - { - node->getExpression()->traverse(this); - } - - out << ")\n"; - - outputLineDirective(node->getLine().first_line); - out << "{\n"; - } - - if (node->getBody()) - { - traverseStatements(node->getBody()); - } - - outputLineDirective(node->getLine().first_line); - out << ";}\n"; - - if (node->getType() == ELoopDoWhile) - { - outputLineDirective(node->getCondition()->getLine().first_line); - out << "while(\n"; - - node->getCondition()->traverse(this); - - out << ");"; - } - - out << "}\n"; - - mInsideDiscontinuousLoop = wasDiscontinuous; - - return false; -} - -bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node) -{ - TInfoSinkBase &out = mBody; - - switch (node->getFlowOp()) - { - case EOpKill: outputTriplet(visit, "discard;\n", "", ""); break; - case EOpBreak: - if (visit == PreVisit) - { - if (mExcessiveLoopIndex) - { - out << "{Break"; - mExcessiveLoopIndex->traverse(this); - out << " = true; break;}\n"; - } - else - { - out << "break;\n"; - } - } - break; - case EOpContinue: outputTriplet(visit, "continue;\n", "", ""); break; - case EOpReturn: - if (visit == PreVisit) - { - if (node->getExpression()) - { - out << "return "; - } - else - { - out << "return;\n"; - } - } - else if (visit == PostVisit) - { - if (node->getExpression()) - { - out << ";\n"; - } - } - break; - default: UNREACHABLE(); - } - - return true; -} - -void OutputHLSL::traverseStatements(TIntermNode *node) -{ - if (isSingleStatement(node)) - { - mUnfoldShortCircuit->traverse(node); - } - - node->traverse(this); -} - -bool OutputHLSL::isSingleStatement(TIntermNode *node) -{ - TIntermAggregate *aggregate = node->getAsAggregate(); - - if (aggregate) - { - if (aggregate->getOp() == EOpSequence) - { - return false; - } - else - { - for (TIntermSequence::iterator sit = aggregate->getSequence().begin(); sit != aggregate->getSequence().end(); sit++) - { - if (!isSingleStatement(*sit)) - { - return false; - } - } - - return true; - } - } - - return true; -} - -// Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them -// (The D3D documentation says 255 iterations, but the compiler complains at anything more than 254). -bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) -{ - const int MAX_LOOP_ITERATIONS = 254; - TInfoSinkBase &out = mBody; - - // Parse loops of the form: - // for(int index = initial; index [comparator] limit; index += increment) - TIntermSymbol *index = NULL; - TOperator comparator = EOpNull; - int initial = 0; - int limit = 0; - int increment = 0; - - // Parse index name and intial value - if (node->getInit()) - { - TIntermAggregate *init = node->getInit()->getAsAggregate(); - - if (init) - { - TIntermSequence &sequence = init->getSequence(); - TIntermTyped *variable = sequence[0]->getAsTyped(); - - if (variable && variable->getQualifier() == EvqTemporary) - { - TIntermBinary *assign = variable->getAsBinaryNode(); - - if (assign->getOp() == EOpInitialize) - { - TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode(); - TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion(); - - if (symbol && constant) - { - if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) - { - index = symbol; - initial = constant->getIConst(0); - } - } - } - } - } - } - - // Parse comparator and limit value - if (index != NULL && node->getCondition()) - { - TIntermBinary *test = node->getCondition()->getAsBinaryNode(); - - if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId()) - { - TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion(); - - if (constant) - { - if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) - { - comparator = test->getOp(); - limit = constant->getIConst(0); - } - } - } - } - - // Parse increment - if (index != NULL && comparator != EOpNull && node->getExpression()) - { - TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode(); - TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode(); - - if (binaryTerminal) - { - TOperator op = binaryTerminal->getOp(); - TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion(); - - if (constant) - { - if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) - { - int value = constant->getIConst(0); - - switch (op) - { - case EOpAddAssign: increment = value; break; - case EOpSubAssign: increment = -value; break; - default: UNIMPLEMENTED(); - } - } - } - } - else if (unaryTerminal) - { - TOperator op = unaryTerminal->getOp(); - - switch (op) - { - case EOpPostIncrement: increment = 1; break; - case EOpPostDecrement: increment = -1; break; - case EOpPreIncrement: increment = 1; break; - case EOpPreDecrement: increment = -1; break; - default: UNIMPLEMENTED(); - } - } - } - - if (index != NULL && comparator != EOpNull && increment != 0) - { - if (comparator == EOpLessThanEqual) - { - comparator = EOpLessThan; - limit += 1; - } - - if (comparator == EOpLessThan) - { - int iterations = (limit - initial) / increment; - - if (iterations <= MAX_LOOP_ITERATIONS) - { - return false; // Not an excessive loop - } - - TIntermSymbol *restoreIndex = mExcessiveLoopIndex; - mExcessiveLoopIndex = index; - - out << "{int "; - index->traverse(this); - out << ";\n" - "bool Break"; - index->traverse(this); - out << " = false;\n"; - - bool firstLoopFragment = true; - - while (iterations > 0) - { - int clampedLimit = initial + increment * std::min(MAX_LOOP_ITERATIONS, iterations); - - if (!firstLoopFragment) - { - out << "if(!Break"; - index->traverse(this); - out << ") {\n"; - } - - if (iterations <= MAX_LOOP_ITERATIONS) // Last loop fragment - { - mExcessiveLoopIndex = NULL; // Stops setting the Break flag - } - - // for(int index = initial; index < clampedLimit; index += increment) - - out << "for("; - index->traverse(this); - out << " = "; - out << initial; - - out << "; "; - index->traverse(this); - out << " < "; - out << clampedLimit; - - out << "; "; - index->traverse(this); - out << " += "; - out << increment; - out << ")\n"; - - outputLineDirective(node->getLine().first_line); - out << "{\n"; - - if (node->getBody()) - { - node->getBody()->traverse(this); - } - - outputLineDirective(node->getLine().first_line); - out << ";}\n"; - - if (!firstLoopFragment) - { - out << "}\n"; - } - - firstLoopFragment = false; - - initial += MAX_LOOP_ITERATIONS * increment; - iterations -= MAX_LOOP_ITERATIONS; - } - - out << "}"; - - mExcessiveLoopIndex = restoreIndex; - - return true; - } - else UNIMPLEMENTED(); - } - - return false; // Not handled as an excessive loop -} - -void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString) -{ - TInfoSinkBase &out = mBody; - - if (visit == PreVisit) - { - out << preString; - } - else if (visit == InVisit) - { - out << inString; - } - else if (visit == PostVisit) - { - out << postString; - } -} - -void OutputHLSL::outputLineDirective(int line) -{ - if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0)) - { - mBody << "\n"; - mBody << "#line " << line; - - if (mContext.sourcePath) - { - mBody << " \"" << mContext.sourcePath << "\""; - } - - mBody << "\n"; - } -} - -TString OutputHLSL::argumentString(const TIntermSymbol *symbol) -{ - TQualifier qualifier = symbol->getQualifier(); - const TType &type = symbol->getType(); - TString name = symbol->getSymbol(); - - if (name.empty()) // HLSL demands named arguments, also for prototypes - { - name = "x" + str(mUniqueIndex++); - } - else - { - name = decorate(name); - } - - if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) - { - return qualifierString(qualifier) + " " + textureString(type) + " texture_" + name + arrayString(type) + ", " + - qualifierString(qualifier) + " SamplerState sampler_" + name + arrayString(type); - } - - return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type); -} - -TString OutputHLSL::qualifierString(TQualifier qualifier) -{ - switch(qualifier) - { - case EvqIn: return "in"; - case EvqOut: return "out"; - case EvqInOut: return "inout"; - case EvqConstReadOnly: return "const"; - default: UNREACHABLE(); - } - - return ""; -} - -TString OutputHLSL::typeString(const TType &type) -{ - if (type.getBasicType() == EbtStruct) - { - const TString& typeName = type.getStruct()->name(); - if (typeName != "") - { - return structLookup(typeName); - } - else // Nameless structure, define in place - { - const TFieldList &fields = type.getStruct()->fields(); - - TString string = "struct\n" - "{\n"; - - for (unsigned int i = 0; i < fields.size(); i++) - { - const TField *field = fields[i]; - - string += " " + typeString(*field->type()) + " " + decorate(field->name()) + arrayString(*field->type()) + ";\n"; - } - - string += "} "; - - return string; - } - } - else if (type.isMatrix()) - { - switch (type.getNominalSize()) - { - case 2: return "float2x2"; - case 3: return "float3x3"; - case 4: return "float4x4"; - } - } - else - { - switch (type.getBasicType()) - { - case EbtFloat: - switch (type.getNominalSize()) - { - case 1: return "float"; - case 2: return "float2"; - case 3: return "float3"; - case 4: return "float4"; - } - case EbtInt: - switch (type.getNominalSize()) - { - case 1: return "int"; - case 2: return "int2"; - case 3: return "int3"; - case 4: return "int4"; - } - case EbtBool: - switch (type.getNominalSize()) - { - case 1: return "bool"; - case 2: return "bool2"; - case 3: return "bool3"; - case 4: return "bool4"; - } - case EbtVoid: - return "void"; - case EbtSampler2D: - return "sampler2D"; - case EbtSamplerCube: - return "samplerCUBE"; - case EbtSamplerExternalOES: - return "sampler2D"; - default: - break; - } - } - - UNREACHABLE(); - return ""; -} - -TString OutputHLSL::textureString(const TType &type) -{ - switch (type.getBasicType()) - { - case EbtSampler2D: - return "Texture2D"; - case EbtSamplerCube: - return "TextureCube"; - case EbtSamplerExternalOES: - return "Texture2D"; - default: - break; - } - - UNREACHABLE(); - return ""; -} - -TString OutputHLSL::arrayString(const TType &type) -{ - if (!type.isArray()) - { - return ""; - } - - return "[" + str(type.getArraySize()) + "]"; -} - -TString OutputHLSL::initializer(const TType &type) -{ - TString string; - - size_t size = type.getObjectSize(); - for (size_t component = 0; component < size; component++) - { - string += "0"; - - if (component + 1 < size) - { - string += ", "; - } - } - - return "{" + string + "}"; -} - -void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters) -{ - if (name == "") - { - return; // Nameless structures don't have constructors - } - - if (type.getStruct() && mStructNames.find(decorate(name)) != mStructNames.end()) - { - return; // Already added - } - - TType ctorType = type; - ctorType.clearArrayness(); - ctorType.setPrecision(EbpHigh); - ctorType.setQualifier(EvqTemporary); - - TString ctorName = type.getStruct() ? decorate(name) : name; - - typedef std::vector ParameterArray; - ParameterArray ctorParameters; - - if (type.getStruct()) - { - mStructNames.insert(decorate(name)); - - TString structure; - structure += "struct " + decorate(name) + "\n" - "{\n"; - - const TFieldList &fields = type.getStruct()->fields(); - - for (unsigned int i = 0; i < fields.size(); i++) - { - const TField *field = fields[i]; - - structure += " " + typeString(*field->type()) + " " + decorateField(field->name(), type) + arrayString(*field->type()) + ";\n"; - } - - structure += "};\n"; - - if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structure) == mStructDeclarations.end()) - { - mStructDeclarations.push_back(structure); - } - - for (unsigned int i = 0; i < fields.size(); i++) - { - ctorParameters.push_back(*fields[i]->type()); - } - } - else if (parameters) - { - for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++) - { - ctorParameters.push_back((*parameter)->getAsTyped()->getType()); - } - } - else UNREACHABLE(); - - TString constructor; - - if (ctorType.getStruct()) - { - constructor += ctorName + " " + ctorName + "_ctor("; - } - else // Built-in type - { - constructor += typeString(ctorType) + " " + ctorName + "("; - } - - for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++) - { - const TType &type = ctorParameters[parameter]; - - constructor += typeString(type) + " x" + str(parameter) + arrayString(type); - - if (parameter < ctorParameters.size() - 1) - { - constructor += ", "; - } - } - - constructor += ")\n" - "{\n"; - - if (ctorType.getStruct()) - { - constructor += " " + ctorName + " structure = {"; - } - else - { - constructor += " return " + typeString(ctorType) + "("; - } - - if (ctorType.isMatrix() && ctorParameters.size() == 1) - { - int dim = ctorType.getNominalSize(); - const TType ¶meter = ctorParameters[0]; - - if (parameter.isScalar()) - { - for (int row = 0; row < dim; row++) - { - for (int col = 0; col < dim; col++) - { - constructor += TString((row == col) ? "x0" : "0.0"); - - if (row < dim - 1 || col < dim - 1) - { - constructor += ", "; - } - } - } - } - else if (parameter.isMatrix()) - { - for (int row = 0; row < dim; row++) - { - for (int col = 0; col < dim; col++) - { - if (row < parameter.getNominalSize() && col < parameter.getNominalSize()) - { - constructor += TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]"; - } - else - { - constructor += TString((row == col) ? "1.0" : "0.0"); - } - - if (row < dim - 1 || col < dim - 1) - { - constructor += ", "; - } - } - } - } - else UNREACHABLE(); - } - else - { - size_t remainingComponents = ctorType.getObjectSize(); - size_t parameterIndex = 0; - - while (remainingComponents > 0) - { - const TType ¶meter = ctorParameters[parameterIndex]; - const size_t parameterSize = parameter.getObjectSize(); - bool moreParameters = parameterIndex + 1 < ctorParameters.size(); - - constructor += "x" + str(parameterIndex); - - if (parameter.isScalar()) - { - ASSERT(parameterSize <= remainingComponents); - remainingComponents -= parameterSize; - } - else if (parameter.isVector()) - { - if (remainingComponents == parameterSize || moreParameters) - { - ASSERT(parameterSize <= remainingComponents); - remainingComponents -= parameterSize; - } - else if (remainingComponents < static_cast(parameter.getNominalSize())) - { - switch (remainingComponents) - { - case 1: constructor += ".x"; break; - case 2: constructor += ".xy"; break; - case 3: constructor += ".xyz"; break; - case 4: constructor += ".xyzw"; break; - default: UNREACHABLE(); - } - - remainingComponents = 0; - } - else UNREACHABLE(); - } - else if (parameter.isMatrix() || parameter.getStruct()) - { - ASSERT(remainingComponents == parameterSize || moreParameters); - ASSERT(parameterSize <= remainingComponents); - - remainingComponents -= parameterSize; - } - else UNREACHABLE(); - - if (moreParameters) - { - parameterIndex++; - } - - if (remainingComponents) - { - constructor += ", "; - } - } - } - - if (ctorType.getStruct()) - { - constructor += "};\n" - " return structure;\n" - "}\n"; - } - else - { - constructor += ");\n" - "}\n"; - } - - mConstructors.insert(constructor); -} - -const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion) -{ - TInfoSinkBase &out = mBody; - - if (type.getBasicType() == EbtStruct) - { - out << structLookup(type.getStruct()->name()) + "_ctor("; - - const TFieldList &fields = type.getStruct()->fields(); - - for (size_t i = 0; i < fields.size(); i++) - { - const TType *fieldType = fields[i]->type(); - - constUnion = writeConstantUnion(*fieldType, constUnion); - - if (i != fields.size() - 1) - { - out << ", "; - } - } - - out << ")"; - } - else - { - size_t size = type.getObjectSize(); - bool writeType = size > 1; - - if (writeType) - { - out << typeString(type) << "("; - } - - for (size_t i = 0; i < size; i++, constUnion++) - { - switch (constUnion->getType()) - { - case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, constUnion->getFConst())); break; - case EbtInt: out << constUnion->getIConst(); break; - case EbtBool: out << constUnion->getBConst(); break; - default: UNREACHABLE(); - } - - if (i != size - 1) - { - out << ", "; - } - } - - if (writeType) - { - out << ")"; - } - } - - return constUnion; -} - -TString OutputHLSL::scopeString(unsigned int depthLimit) -{ - TString string; - - for (unsigned int i = 0; i < mScopeBracket.size() && i < depthLimit; i++) - { - string += "_" + str(i); - } - - return string; -} - -TString OutputHLSL::scopedStruct(const TString &typeName) -{ - if (typeName == "") - { - return typeName; - } - - return typeName + scopeString(mScopeDepth); -} - -TString OutputHLSL::structLookup(const TString &typeName) -{ - for (int depth = mScopeDepth; depth >= 0; depth--) - { - TString scopedName = decorate(typeName + scopeString(depth)); - - for (StructNames::iterator structName = mStructNames.begin(); structName != mStructNames.end(); structName++) - { - if (*structName == scopedName) - { - return scopedName; - } - } - } - - UNREACHABLE(); // Should have found a matching constructor - - return typeName; -} - -TString OutputHLSL::decorate(const TString &string) -{ - if (string.compare(0, 3, "gl_") != 0 && string.compare(0, 3, "dx_") != 0) - { - return "_" + string; - } - - return string; -} - -TString OutputHLSL::decorateUniform(const TString &string, const TType &type) -{ - if (type.getBasicType() == EbtSamplerExternalOES) - { - return "ex_" + string; - } - - return decorate(string); -} - -TString OutputHLSL::decorateField(const TString &string, const TType &structure) -{ - if (structure.getStruct()->name().compare(0, 3, "gl_") != 0) - { - return decorate(string); - } - - return string; -} - -TString OutputHLSL::registerString(TIntermSymbol *operand) -{ - ASSERT(operand->getQualifier() == EvqUniform); - - if (IsSampler(operand->getBasicType())) - { - return "s" + str(samplerRegister(operand)); - } - - return "c" + str(uniformRegister(operand)); -} - -int OutputHLSL::samplerRegister(TIntermSymbol *sampler) -{ - const TType &type = sampler->getType(); - ASSERT(IsSampler(type.getBasicType())); - - int index = mSamplerRegister; - mSamplerRegister += sampler->totalRegisterCount(); - - declareUniform(type, sampler->getSymbol(), index); - - return index; -} - -int OutputHLSL::uniformRegister(TIntermSymbol *uniform) -{ - const TType &type = uniform->getType(); - ASSERT(!IsSampler(type.getBasicType())); - - int index = mUniformRegister; - mUniformRegister += uniform->totalRegisterCount(); - - declareUniform(type, uniform->getSymbol(), index); - - return index; -} - -void OutputHLSL::declareUniform(const TType &type, const TString &name, int index) -{ - TStructure *structure = type.getStruct(); - - if (!structure) - { - mActiveUniforms.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), type.getArraySize(), index)); - } - else - { - const TFieldList &fields = structure->fields(); - - if (type.isArray()) - { - int elementIndex = index; - - for (int i = 0; i < type.getArraySize(); i++) - { - for (size_t j = 0; j < fields.size(); j++) - { - const TType &fieldType = *fields[j]->type(); - const TString uniformName = name + "[" + str(i) + "]." + fields[j]->name(); - declareUniform(fieldType, uniformName, elementIndex); - elementIndex += fieldType.totalRegisterCount(); - } - } - } - else - { - int fieldIndex = index; - - for (size_t i = 0; i < fields.size(); i++) - { - const TType &fieldType = *fields[i]->type(); - const TString uniformName = name + "." + fields[i]->name(); - declareUniform(fieldType, uniformName, fieldIndex); - fieldIndex += fieldType.totalRegisterCount(); - } - } - } -} - -GLenum OutputHLSL::glVariableType(const TType &type) -{ - if (type.getBasicType() == EbtFloat) - { - if (type.isScalar()) - { - return GL_FLOAT; - } - else if (type.isVector()) - { - switch(type.getNominalSize()) - { - case 2: return GL_FLOAT_VEC2; - case 3: return GL_FLOAT_VEC3; - case 4: return GL_FLOAT_VEC4; - default: UNREACHABLE(); - } - } - else if (type.isMatrix()) - { - switch(type.getNominalSize()) - { - case 2: return GL_FLOAT_MAT2; - case 3: return GL_FLOAT_MAT3; - case 4: return GL_FLOAT_MAT4; - default: UNREACHABLE(); - } - } - else UNREACHABLE(); - } - else if (type.getBasicType() == EbtInt) - { - if (type.isScalar()) - { - return GL_INT; - } - else if (type.isVector()) - { - switch(type.getNominalSize()) - { - case 2: return GL_INT_VEC2; - case 3: return GL_INT_VEC3; - case 4: return GL_INT_VEC4; - default: UNREACHABLE(); - } - } - else UNREACHABLE(); - } - else if (type.getBasicType() == EbtBool) - { - if (type.isScalar()) - { - return GL_BOOL; - } - else if (type.isVector()) - { - switch(type.getNominalSize()) - { - case 2: return GL_BOOL_VEC2; - case 3: return GL_BOOL_VEC3; - case 4: return GL_BOOL_VEC4; - default: UNREACHABLE(); - } - } - else UNREACHABLE(); - } - else if (type.getBasicType() == EbtSampler2D) - { - return GL_SAMPLER_2D; - } - else if (type.getBasicType() == EbtSamplerCube) - { - return GL_SAMPLER_CUBE; - } - else UNREACHABLE(); - - return GL_NONE; -} - -GLenum OutputHLSL::glVariablePrecision(const TType &type) -{ - if (type.getBasicType() == EbtFloat) - { - switch (type.getPrecision()) - { - case EbpHigh: return GL_HIGH_FLOAT; - case EbpMedium: return GL_MEDIUM_FLOAT; - case EbpLow: return GL_LOW_FLOAT; - case EbpUndefined: - // Should be defined as the default precision by the parser - default: UNREACHABLE(); - } - } - else if (type.getBasicType() == EbtInt) - { - switch (type.getPrecision()) - { - case EbpHigh: return GL_HIGH_INT; - case EbpMedium: return GL_MEDIUM_INT; - case EbpLow: return GL_LOW_INT; - case EbpUndefined: - // Should be defined as the default precision by the parser - default: UNREACHABLE(); - } - } - - // Other types (boolean, sampler) don't have a precision - return GL_NONE; -} - -} diff --git a/src/3rdparty/angle/src/compiler/OutputHLSL.h b/src/3rdparty/angle/src/compiler/OutputHLSL.h deleted file mode 100644 index cde4120718..0000000000 --- a/src/3rdparty/angle/src/compiler/OutputHLSL.h +++ /dev/null @@ -1,166 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_OUTPUTHLSL_H_ -#define COMPILER_OUTPUTHLSL_H_ - -#include -#include -#include - -#define GL_APICALL -#include - -#include "compiler/intermediate.h" -#include "compiler/ParseHelper.h" -#include "compiler/Uniform.h" - -namespace sh -{ -class UnfoldShortCircuit; - -class OutputHLSL : public TIntermTraverser -{ - public: - OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType); - ~OutputHLSL(); - - void output(); - - TInfoSinkBase &getBodyStream(); - const ActiveUniforms &getUniforms(); - - TString typeString(const TType &type); - TString textureString(const TType &type); - static TString qualifierString(TQualifier qualifier); - static TString arrayString(const TType &type); - static TString initializer(const TType &type); - static TString decorate(const TString &string); // Prepends an underscore to avoid naming clashes - static TString decorateUniform(const TString &string, const TType &type); - static TString decorateField(const TString &string, const TType &structure); - - protected: - void header(); - - // Visit AST nodes and output their code to the body stream - void visitSymbol(TIntermSymbol*); - void visitConstantUnion(TIntermConstantUnion*); - bool visitBinary(Visit visit, TIntermBinary*); - bool visitUnary(Visit visit, TIntermUnary*); - bool visitSelection(Visit visit, TIntermSelection*); - bool visitAggregate(Visit visit, TIntermAggregate*); - bool visitLoop(Visit visit, TIntermLoop*); - bool visitBranch(Visit visit, TIntermBranch*); - - void traverseStatements(TIntermNode *node); - bool isSingleStatement(TIntermNode *node); - bool handleExcessiveLoop(TIntermLoop *node); - void outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString); - void outputLineDirective(int line); - TString argumentString(const TIntermSymbol *symbol); - int vectorSize(const TType &type) const; - - void addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters); - const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion); - - TString scopeString(unsigned int depthLimit); - TString scopedStruct(const TString &typeName); - TString structLookup(const TString &typeName); - - TParseContext &mContext; - const ShShaderOutput mOutputType; - UnfoldShortCircuit *mUnfoldShortCircuit; - bool mInsideFunction; - - // Output streams - TInfoSinkBase mHeader; - TInfoSinkBase mBody; - TInfoSinkBase mFooter; - - typedef std::map ReferencedSymbols; - ReferencedSymbols mReferencedUniforms; - ReferencedSymbols mReferencedAttributes; - ReferencedSymbols mReferencedVaryings; - - // Parameters determining what goes in the header output - bool mUsesTexture2D; - bool mUsesTexture2D_bias; - bool mUsesTexture2DLod; - bool mUsesTexture2DProj; - bool mUsesTexture2DProj_bias; - bool mUsesTexture2DProjLod; - bool mUsesTextureCube; - bool mUsesTextureCube_bias; - bool mUsesTextureCubeLod; - bool mUsesTexture2DLod0; - bool mUsesTexture2DLod0_bias; - bool mUsesTexture2DProjLod0; - bool mUsesTexture2DProjLod0_bias; - bool mUsesTextureCubeLod0; - bool mUsesTextureCubeLod0_bias; - bool mUsesFragColor; - bool mUsesFragData; - bool mUsesDepthRange; - bool mUsesFragCoord; - bool mUsesPointCoord; - bool mUsesFrontFacing; - bool mUsesPointSize; - bool mUsesFragDepth; - bool mUsesXor; - bool mUsesMod1; - bool mUsesMod2v; - bool mUsesMod2f; - bool mUsesMod3v; - bool mUsesMod3f; - bool mUsesMod4v; - bool mUsesMod4f; - bool mUsesFaceforward1; - bool mUsesFaceforward2; - bool mUsesFaceforward3; - bool mUsesFaceforward4; - bool mUsesAtan2_1; - bool mUsesAtan2_2; - bool mUsesAtan2_3; - bool mUsesAtan2_4; - - int mNumRenderTargets; - - typedef std::set Constructors; - Constructors mConstructors; - - typedef std::set StructNames; - StructNames mStructNames; - - typedef std::list StructDeclarations; - StructDeclarations mStructDeclarations; - - typedef std::vector ScopeBracket; - ScopeBracket mScopeBracket; - unsigned int mScopeDepth; - - int mUniqueIndex; // For creating unique names - - bool mContainsLoopDiscontinuity; - bool mOutputLod0Function; - bool mInsideDiscontinuousLoop; - - TIntermSymbol *mExcessiveLoopIndex; - - int mUniformRegister; - int mSamplerRegister; - - TString registerString(TIntermSymbol *operand); - int samplerRegister(TIntermSymbol *sampler); - int uniformRegister(TIntermSymbol *uniform); - void declareUniform(const TType &type, const TString &name, int index); - static GLenum glVariableType(const TType &type); - static GLenum glVariablePrecision(const TType &type); - - ActiveUniforms mActiveUniforms; -}; -} - -#endif // COMPILER_OUTPUTHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/ParseHelper.cpp b/src/3rdparty/angle/src/compiler/ParseHelper.cpp deleted file mode 100644 index 1f8538e6a4..0000000000 --- a/src/3rdparty/angle/src/compiler/ParseHelper.cpp +++ /dev/null @@ -1,1602 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/ParseHelper.h" - -#include -#include - -#include "compiler/glslang.h" -#include "compiler/preprocessor/SourceLocation.h" - -/////////////////////////////////////////////////////////////////////// -// -// Sub- vector and matrix fields -// -//////////////////////////////////////////////////////////////////////// - -// -// Look at a '.' field selector string and change it into offsets -// for a vector. -// -bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, const TSourceLoc& line) -{ - fields.num = (int) compString.size(); - if (fields.num > 4) { - error(line, "illegal vector field selection", compString.c_str()); - return false; - } - - enum { - exyzw, - ergba, - estpq - } fieldSet[4]; - - for (int i = 0; i < fields.num; ++i) { - switch (compString[i]) { - case 'x': - fields.offsets[i] = 0; - fieldSet[i] = exyzw; - break; - case 'r': - fields.offsets[i] = 0; - fieldSet[i] = ergba; - break; - case 's': - fields.offsets[i] = 0; - fieldSet[i] = estpq; - break; - case 'y': - fields.offsets[i] = 1; - fieldSet[i] = exyzw; - break; - case 'g': - fields.offsets[i] = 1; - fieldSet[i] = ergba; - break; - case 't': - fields.offsets[i] = 1; - fieldSet[i] = estpq; - break; - case 'z': - fields.offsets[i] = 2; - fieldSet[i] = exyzw; - break; - case 'b': - fields.offsets[i] = 2; - fieldSet[i] = ergba; - break; - case 'p': - fields.offsets[i] = 2; - fieldSet[i] = estpq; - break; - - case 'w': - fields.offsets[i] = 3; - fieldSet[i] = exyzw; - break; - case 'a': - fields.offsets[i] = 3; - fieldSet[i] = ergba; - break; - case 'q': - fields.offsets[i] = 3; - fieldSet[i] = estpq; - break; - default: - error(line, "illegal vector field selection", compString.c_str()); - return false; - } - } - - for (int i = 0; i < fields.num; ++i) { - if (fields.offsets[i] >= vecSize) { - error(line, "vector field selection out of range", compString.c_str()); - return false; - } - - if (i > 0) { - if (fieldSet[i] != fieldSet[i-1]) { - error(line, "illegal - vector component fields not from the same set", compString.c_str()); - return false; - } - } - } - - return true; -} - - -// -// Look at a '.' field selector string and change it into offsets -// for a matrix. -// -bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, const TSourceLoc& line) -{ - fields.wholeRow = false; - fields.wholeCol = false; - fields.row = -1; - fields.col = -1; - - if (compString.size() != 2) { - error(line, "illegal length of matrix field selection", compString.c_str()); - return false; - } - - if (compString[0] == '_') { - if (compString[1] < '0' || compString[1] > '3') { - error(line, "illegal matrix field selection", compString.c_str()); - return false; - } - fields.wholeCol = true; - fields.col = compString[1] - '0'; - } else if (compString[1] == '_') { - if (compString[0] < '0' || compString[0] > '3') { - error(line, "illegal matrix field selection", compString.c_str()); - return false; - } - fields.wholeRow = true; - fields.row = compString[0] - '0'; - } else { - if (compString[0] < '0' || compString[0] > '3' || - compString[1] < '0' || compString[1] > '3') { - error(line, "illegal matrix field selection", compString.c_str()); - return false; - } - fields.row = compString[0] - '0'; - fields.col = compString[1] - '0'; - } - - if (fields.row >= matSize || fields.col >= matSize) { - error(line, "matrix field selection out of range", compString.c_str()); - return false; - } - - return true; -} - -/////////////////////////////////////////////////////////////////////// -// -// Errors -// -//////////////////////////////////////////////////////////////////////// - -// -// Track whether errors have occurred. -// -void TParseContext::recover() -{ -} - -// -// Used by flex/bison to output all syntax and parsing errors. -// -void TParseContext::error(const TSourceLoc& loc, - const char* reason, const char* token, - const char* extraInfo) -{ - pp::SourceLocation srcLoc; - srcLoc.file = loc.first_file; - srcLoc.line = loc.first_line; - diagnostics.writeInfo(pp::Diagnostics::ERROR, - srcLoc, reason, token, extraInfo); - -} - -void TParseContext::warning(const TSourceLoc& loc, - const char* reason, const char* token, - const char* extraInfo) { - pp::SourceLocation srcLoc; - srcLoc.file = loc.first_file; - srcLoc.line = loc.first_line; - diagnostics.writeInfo(pp::Diagnostics::WARNING, - srcLoc, reason, token, extraInfo); -} - -void TParseContext::trace(const char* str) -{ - diagnostics.writeDebug(str); -} - -// -// Same error message for all places assignments don't work. -// -void TParseContext::assignError(const TSourceLoc& line, const char* op, TString left, TString right) -{ - std::stringstream extraInfoStream; - extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'"; - std::string extraInfo = extraInfoStream.str(); - error(line, "", op, extraInfo.c_str()); -} - -// -// Same error message for all places unary operations don't work. -// -void TParseContext::unaryOpError(const TSourceLoc& line, const char* op, TString operand) -{ - std::stringstream extraInfoStream; - extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand - << " (or there is no acceptable conversion)"; - std::string extraInfo = extraInfoStream.str(); - error(line, " wrong operand type", op, extraInfo.c_str()); -} - -// -// Same error message for all binary operations don't work. -// -void TParseContext::binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right) -{ - std::stringstream extraInfoStream; - extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left - << "' and a right operand of type '" << right << "' (or there is no acceptable conversion)"; - std::string extraInfo = extraInfoStream.str(); - error(line, " wrong operand types ", op, extraInfo.c_str()); -} - -bool TParseContext::precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type){ - if (!checksPrecisionErrors) - return false; - switch( type ){ - case EbtFloat: - if( precision == EbpUndefined ){ - error( line, "No precision specified for (float)", "" ); - return true; - } - break; - case EbtInt: - if( precision == EbpUndefined ){ - error( line, "No precision specified (int)", "" ); - return true; - } - break; - default: - return false; - } - return false; -} - -// -// Both test and if necessary, spit out an error, to see if the node is really -// an l-value that can be operated on this way. -// -// Returns true if the was an error. -// -bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped* node) -{ - TIntermSymbol* symNode = node->getAsSymbolNode(); - TIntermBinary* binaryNode = node->getAsBinaryNode(); - - if (binaryNode) { - bool errorReturn; - - switch(binaryNode->getOp()) { - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectStruct: - return lValueErrorCheck(line, op, binaryNode->getLeft()); - case EOpVectorSwizzle: - errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft()); - if (!errorReturn) { - int offset[4] = {0,0,0,0}; - - TIntermTyped* rightNode = binaryNode->getRight(); - TIntermAggregate *aggrNode = rightNode->getAsAggregate(); - - for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); - p != aggrNode->getSequence().end(); p++) { - int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0); - offset[value]++; - if (offset[value] > 1) { - error(line, " l-value of swizzle cannot have duplicate components", op); - - return true; - } - } - } - - return errorReturn; - default: - break; - } - error(line, " l-value required", op); - - return true; - } - - - const char* symbol = 0; - if (symNode != 0) - symbol = symNode->getSymbol().c_str(); - - const char* message = 0; - switch (node->getQualifier()) { - case EvqConst: message = "can't modify a const"; break; - case EvqConstReadOnly: message = "can't modify a const"; break; - case EvqAttribute: message = "can't modify an attribute"; break; - case EvqUniform: message = "can't modify a uniform"; break; - case EvqVaryingIn: message = "can't modify a varying"; break; - case EvqFragCoord: message = "can't modify gl_FragCoord"; break; - case EvqFrontFacing: message = "can't modify gl_FrontFacing"; break; - case EvqPointCoord: message = "can't modify gl_PointCoord"; break; - default: - - // - // Type that can't be written to? - // - switch (node->getBasicType()) { - case EbtSampler2D: - case EbtSamplerCube: - message = "can't modify a sampler"; - break; - case EbtVoid: - message = "can't modify void"; - break; - default: - break; - } - } - - if (message == 0 && binaryNode == 0 && symNode == 0) { - error(line, " l-value required", op); - - return true; - } - - - // - // Everything else is okay, no error. - // - if (message == 0) - return false; - - // - // If we get here, we have an error and a message. - // - if (symNode) { - std::stringstream extraInfoStream; - extraInfoStream << "\"" << symbol << "\" (" << message << ")"; - std::string extraInfo = extraInfoStream.str(); - error(line, " l-value required", op, extraInfo.c_str()); - } - else { - std::stringstream extraInfoStream; - extraInfoStream << "(" << message << ")"; - std::string extraInfo = extraInfoStream.str(); - error(line, " l-value required", op, extraInfo.c_str()); - } - - return true; -} - -// -// Both test, and if necessary spit out an error, to see if the node is really -// a constant. -// -// Returns true if the was an error. -// -bool TParseContext::constErrorCheck(TIntermTyped* node) -{ - if (node->getQualifier() == EvqConst) - return false; - - error(node->getLine(), "constant expression required", ""); - - return true; -} - -// -// Both test, and if necessary spit out an error, to see if the node is really -// an integer. -// -// Returns true if the was an error. -// -bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token) -{ - if (node->getBasicType() == EbtInt && node->getNominalSize() == 1) - return false; - - error(node->getLine(), "integer expression required", token); - - return true; -} - -// -// Both test, and if necessary spit out an error, to see if we are currently -// globally scoped. -// -// Returns true if the was an error. -// -bool TParseContext::globalErrorCheck(const TSourceLoc& line, bool global, const char* token) -{ - if (global) - return false; - - error(line, "only allowed at global scope", token); - - return true; -} - -// -// For now, keep it simple: if it starts "gl_", it's reserved, independent -// of scope. Except, if the symbol table is at the built-in push-level, -// which is when we are parsing built-ins. -// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a -// webgl shader. -// -// Returns true if there was an error. -// -bool TParseContext::reservedErrorCheck(const TSourceLoc& line, const TString& identifier) -{ - static const char* reservedErrMsg = "reserved built-in name"; - if (!symbolTable.atBuiltInLevel()) { - if (identifier.compare(0, 3, "gl_") == 0) { - error(line, reservedErrMsg, "gl_"); - return true; - } - if (isWebGLBasedSpec(shaderSpec)) { - if (identifier.compare(0, 6, "webgl_") == 0) { - error(line, reservedErrMsg, "webgl_"); - return true; - } - if (identifier.compare(0, 7, "_webgl_") == 0) { - error(line, reservedErrMsg, "_webgl_"); - return true; - } - if (shaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0) { - error(line, reservedErrMsg, "css_"); - return true; - } - } - if (identifier.find("__") != TString::npos) { - error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str()); - return true; - } - } - - return false; -} - -// -// Make sure there is enough data provided to the constructor to build -// something of the type of the constructor. Also returns the type of -// the constructor. -// -// Returns true if there was an error in construction. -// -bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* node, TFunction& function, TOperator op, TType* type) -{ - *type = function.getReturnType(); - - bool constructingMatrix = false; - switch(op) { - case EOpConstructMat2: - case EOpConstructMat3: - case EOpConstructMat4: - constructingMatrix = true; - break; - default: - break; - } - - // - // Note: It's okay to have too many components available, but not okay to have unused - // arguments. 'full' will go to true when enough args have been seen. If we loop - // again, there is an extra argument, so 'overfull' will become true. - // - - size_t size = 0; - bool constType = true; - bool full = false; - bool overFull = false; - bool matrixInMatrix = false; - bool arrayArg = false; - for (size_t i = 0; i < function.getParamCount(); ++i) { - const TParameter& param = function.getParam(i); - size += param.type->getObjectSize(); - - if (constructingMatrix && param.type->isMatrix()) - matrixInMatrix = true; - if (full) - overFull = true; - if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize()) - full = true; - if (param.type->getQualifier() != EvqConst) - constType = false; - if (param.type->isArray()) - arrayArg = true; - } - - if (constType) - type->setQualifier(EvqConst); - - if (type->isArray() && static_cast(type->getArraySize()) != function.getParamCount()) { - error(line, "array constructor needs one argument per array element", "constructor"); - return true; - } - - if (arrayArg && op != EOpConstructStruct) { - error(line, "constructing from a non-dereferenced array", "constructor"); - return true; - } - - if (matrixInMatrix && !type->isArray()) { - if (function.getParamCount() != 1) { - error(line, "constructing matrix from matrix can only take one argument", "constructor"); - return true; - } - } - - if (overFull) { - error(line, "too many arguments", "constructor"); - return true; - } - - if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->fields().size()) != function.getParamCount()) { - error(line, "Number of constructor parameters does not match the number of structure fields", "constructor"); - return true; - } - - if (!type->isMatrix() || !matrixInMatrix) { - if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) || - (op == EOpConstructStruct && size < type->getObjectSize())) { - error(line, "not enough data provided for construction", "constructor"); - return true; - } - } - - TIntermTyped *typed = node ? node->getAsTyped() : 0; - if (typed == 0) { - error(line, "constructor argument does not have a type", "constructor"); - return true; - } - if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) { - error(line, "cannot convert a sampler", "constructor"); - return true; - } - if (typed->getBasicType() == EbtVoid) { - error(line, "cannot convert a void", "constructor"); - return true; - } - - return false; -} - -// This function checks to see if a void variable has been declared and raise an error message for such a case -// -// returns true in case of an error -// -bool TParseContext::voidErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& pubType) -{ - if (pubType.type == EbtVoid) { - error(line, "illegal use of type 'void'", identifier.c_str()); - return true; - } - - return false; -} - -// This function checks to see if the node (for the expression) contains a scalar boolean expression or not -// -// returns true in case of an error -// -bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TIntermTyped* type) -{ - if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) { - error(line, "boolean expression expected", ""); - return true; - } - - return false; -} - -// This function checks to see if the node (for the expression) contains a scalar boolean expression or not -// -// returns true in case of an error -// -bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TPublicType& pType) -{ - if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) { - error(line, "boolean expression expected", ""); - return true; - } - - return false; -} - -bool TParseContext::samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason) -{ - if (pType.type == EbtStruct) { - if (containsSampler(*pType.userDef)) { - error(line, reason, getBasicString(pType.type), "(structure contains a sampler)"); - - return true; - } - - return false; - } else if (IsSampler(pType.type)) { - error(line, reason, getBasicString(pType.type)); - - return true; - } - - return false; -} - -bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType) -{ - if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) && - pType.type == EbtStruct) { - error(line, "cannot be used with a structure", getQualifierString(pType.qualifier)); - - return true; - } - - if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform")) - return true; - - return false; -} - -bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type) -{ - if ((qualifier == EvqOut || qualifier == EvqInOut) && - type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) { - error(line, "samplers cannot be output parameters", type.getBasicString()); - return true; - } - - return false; -} - -bool TParseContext::containsSampler(TType& type) -{ - if (IsSampler(type.getBasicType())) - return true; - - if (type.getBasicType() == EbtStruct) { - const TFieldList& fields = type.getStruct()->fields(); - for (unsigned int i = 0; i < fields.size(); ++i) { - if (containsSampler(*fields[i]->type())) - return true; - } - } - - return false; -} - -// -// Do size checking for an array type's size. -// -// Returns true if there was an error. -// -bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size) -{ - TIntermConstantUnion* constant = expr->getAsConstantUnion(); - if (constant == 0 || constant->getBasicType() != EbtInt) { - error(line, "array size must be a constant integer expression", ""); - return true; - } - - size = constant->getIConst(0); - - if (size <= 0) { - error(line, "array size must be a positive integer", ""); - size = 1; - return true; - } - - return false; -} - -// -// See if this qualifier can be an array. -// -// Returns true if there is an error. -// -bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type) -{ - if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) { - error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str()); - return true; - } - - return false; -} - -// -// See if this type can be an array. -// -// Returns true if there is an error. -// -bool TParseContext::arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type) -{ - // - // Can the type be an array? - // - if (type.array) { - error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str()); - return true; - } - - return false; -} - -// -// Do all the semantic checking for declaring an array, with and -// without a size, and make the right changes to the symbol table. -// -// size == 0 means no specified size. -// -// Returns true if there was an error. -// -bool TParseContext::arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable) -{ - // - // Don't check for reserved word use until after we know it's not in the symbol table, - // because reserved arrays can be redeclared. - // - - bool builtIn = false; - bool sameScope = false; - TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope); - if (symbol == 0 || !sameScope) { - if (reservedErrorCheck(line, identifier)) - return true; - - variable = new TVariable(&identifier, TType(type)); - - if (type.arraySize) - variable->getType().setArraySize(type.arraySize); - - if (! symbolTable.insert(*variable)) { - delete variable; - error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str()); - return true; - } - } else { - if (! symbol->isVariable()) { - error(line, "variable expected", identifier.c_str()); - return true; - } - - variable = static_cast(symbol); - if (! variable->getType().isArray()) { - error(line, "redeclaring non-array as array", identifier.c_str()); - return true; - } - if (variable->getType().getArraySize() > 0) { - error(line, "redeclaration of array with size", identifier.c_str()); - return true; - } - - if (! variable->getType().sameElementType(TType(type))) { - error(line, "redeclaration of array with a different type", identifier.c_str()); - return true; - } - - if (type.arraySize) - variable->getType().setArraySize(type.arraySize); - } - - if (voidErrorCheck(line, identifier, type)) - return true; - - return false; -} - -// -// Enforce non-initializer type/qualifier rules. -// -// Returns true if there was an error. -// -bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array) -{ - if (type.qualifier == EvqConst) - { - // Make the qualifier make sense. - type.qualifier = EvqTemporary; - - if (array) - { - error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str()); - } - else if (type.isStructureContainingArrays()) - { - error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str()); - } - else - { - error(line, "variables with qualifier 'const' must be initialized", identifier.c_str()); - } - - return true; - } - - return false; -} - -// -// Do semantic checking for a variable declaration that has no initializer, -// and update the symbol table. -// -// Returns true if there was an error. -// -bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable) -{ - if (reservedErrorCheck(line, identifier)) - recover(); - - variable = new TVariable(&identifier, TType(type)); - - if (! symbolTable.insert(*variable)) { - error(line, "redefinition", variable->getName().c_str()); - delete variable; - variable = 0; - return true; - } - - if (voidErrorCheck(line, identifier, type)) - return true; - - return false; -} - -bool TParseContext::paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type) -{ - if (qualifier != EvqConst && qualifier != EvqTemporary) { - error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier)); - return true; - } - if (qualifier == EvqConst && paramQualifier != EvqIn) { - error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier)); - return true; - } - - if (qualifier == EvqConst) - type->setQualifier(EvqConstReadOnly); - else - type->setQualifier(paramQualifier); - - return false; -} - -bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& extension) -{ - const TExtensionBehavior& extBehavior = extensionBehavior(); - TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str()); - if (iter == extBehavior.end()) { - error(line, "extension", extension.c_str(), "is not supported"); - return true; - } - // In GLSL ES, an extension's default behavior is "disable". - if (iter->second == EBhDisable || iter->second == EBhUndefined) { - error(line, "extension", extension.c_str(), "is disabled"); - return true; - } - if (iter->second == EBhWarn) { - warning(line, "extension", extension.c_str(), "is being used"); - return false; - } - - return false; -} - -bool TParseContext::supportsExtension(const char* extension) -{ - const TExtensionBehavior& extbehavior = extensionBehavior(); - TExtensionBehavior::const_iterator iter = extbehavior.find(extension); - return (iter != extbehavior.end()); -} - -bool TParseContext::isExtensionEnabled(const char* extension) const -{ - const TExtensionBehavior& extbehavior = extensionBehavior(); - TExtensionBehavior::const_iterator iter = extbehavior.find(extension); - - if (iter == extbehavior.end()) - { - return false; - } - - return (iter->second == EBhEnable || iter->second == EBhRequire); -} - -///////////////////////////////////////////////////////////////////////////////// -// -// Non-Errors. -// -///////////////////////////////////////////////////////////////////////////////// - -// -// Look up a function name in the symbol table, and make sure it is a function. -// -// Return the function symbol if found, otherwise 0. -// -const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, bool *builtIn) -{ - // First find by unmangled name to check whether the function name has been - // hidden by a variable name or struct typename. - // If a function is found, check for one with a matching argument list. - const TSymbol* symbol = symbolTable.find(call->getName(), builtIn); - if (symbol == 0 || symbol->isFunction()) { - symbol = symbolTable.find(call->getMangledName(), builtIn); - } - - if (symbol == 0) { - error(line, "no matching overloaded function found", call->getName().c_str()); - return 0; - } - - if (!symbol->isFunction()) { - error(line, "function name expected", call->getName().c_str()); - return 0; - } - - return static_cast(symbol); -} - -// -// Initializers show up in several places in the grammar. Have one set of -// code to handle them here. -// -bool TParseContext::executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType, - TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) -{ - TType type = TType(pType); - - if (variable == 0) { - if (reservedErrorCheck(line, identifier)) - return true; - - if (voidErrorCheck(line, identifier, pType)) - return true; - - // - // add variable to symbol table - // - variable = new TVariable(&identifier, type); - if (! symbolTable.insert(*variable)) { - error(line, "redefinition", variable->getName().c_str()); - return true; - // don't delete variable, it's used by error recovery, and the pool - // pop will take care of the memory - } - } - - // - // identifier must be of type constant, a global, or a temporary - // - TQualifier qualifier = variable->getType().getQualifier(); - if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) { - error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString()); - return true; - } - // - // test for and propagate constant - // - - if (qualifier == EvqConst) { - if (qualifier != initializer->getType().getQualifier()) { - std::stringstream extraInfoStream; - extraInfoStream << "'" << variable->getType().getCompleteString() << "'"; - std::string extraInfo = extraInfoStream.str(); - error(line, " assigning non-constant to", "=", extraInfo.c_str()); - variable->getType().setQualifier(EvqTemporary); - return true; - } - if (type != initializer->getType()) { - error(line, " non-matching types for const initializer ", - variable->getType().getQualifierString()); - variable->getType().setQualifier(EvqTemporary); - return true; - } - if (initializer->getAsConstantUnion()) { - variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); - } else if (initializer->getAsSymbolNode()) { - const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol()); - const TVariable* tVar = static_cast(symbol); - - ConstantUnion* constArray = tVar->getConstPointer(); - variable->shareConstPointer(constArray); - } else { - std::stringstream extraInfoStream; - extraInfoStream << "'" << variable->getType().getCompleteString() << "'"; - std::string extraInfo = extraInfoStream.str(); - error(line, " cannot assign to", "=", extraInfo.c_str()); - variable->getType().setQualifier(EvqTemporary); - return true; - } - } - - if (qualifier != EvqConst) { - TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line); - intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line); - if (intermNode == 0) { - assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); - return true; - } - } else - intermNode = 0; - - return false; -} - -bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) -{ - ASSERT(aggrNode != NULL); - if (!aggrNode->isConstructor()) - return false; - - bool allConstant = true; - - // check if all the child nodes are constants so that they can be inserted into - // the parent node - TIntermSequence &sequence = aggrNode->getSequence() ; - for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) { - if (!(*p)->getAsTyped()->getAsConstantUnion()) - return false; - } - - return allConstant; -} - -// This function is used to test for the correctness of the parameters passed to various constructor functions -// and also convert them to the right datatype if it is allowed and required. -// -// Returns 0 for an error or the constructed node (aggregate or typed) for no error. -// -TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc& line) -{ - if (node == 0) - return 0; - - TIntermAggregate* aggrNode = node->getAsAggregate(); - - TFieldList::const_iterator memberFields; - if (op == EOpConstructStruct) - memberFields = type->getStruct()->fields().begin(); - - TType elementType = *type; - if (type->isArray()) - elementType.clearArrayness(); - - bool singleArg; - if (aggrNode) { - if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1) - singleArg = true; - else - singleArg = false; - } else - singleArg = true; - - TIntermTyped *newNode; - if (singleArg) { - // If structure constructor or array constructor is being called - // for only one parameter inside the structure, we need to call constructStruct function once. - if (type->isArray()) - newNode = constructStruct(node, &elementType, 1, node->getLine(), false); - else if (op == EOpConstructStruct) - newNode = constructStruct(node, (*memberFields)->type(), 1, node->getLine(), false); - else - newNode = constructBuiltIn(type, op, node, node->getLine(), false); - - if (newNode && newNode->getAsAggregate()) { - TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type); - if (constConstructor) - return constConstructor; - } - - return newNode; - } - - // - // Handle list of arguments. - // - TIntermSequence &sequenceVector = aggrNode->getSequence() ; // Stores the information about the parameter to the constructor - // if the structure constructor contains more than one parameter, then construct - // each parameter - - int paramCount = 0; // keeps a track of the constructor parameter number being checked - - // for each parameter to the constructor call, check to see if the right type is passed or convert them - // to the right type if possible (and allowed). - // for structure constructors, just check if the right type is passed, no conversion is allowed. - - for (TIntermSequence::iterator p = sequenceVector.begin(); - p != sequenceVector.end(); p++, paramCount++) { - if (type->isArray()) - newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true); - else if (op == EOpConstructStruct) - newNode = constructStruct(*p, memberFields[paramCount]->type(), paramCount+1, node->getLine(), true); - else - newNode = constructBuiltIn(type, op, *p, node->getLine(), true); - - if (newNode) { - *p = newNode; - } - } - - TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line); - TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type); - if (constConstructor) - return constConstructor; - - return constructor; -} - -TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type) -{ - bool canBeFolded = areAllChildConst(aggrNode); - aggrNode->setType(type); - if (canBeFolded) { - bool returnVal = false; - ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()]; - if (aggrNode->getSequence().size() == 1) { - returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type, true); - } - else { - returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type); - } - if (returnVal) - return 0; - - return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine()); - } - - return 0; -} - -// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value -// for the parameter to the constructor (passed to this function). Essentially, it converts -// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a -// float, then float is converted to int. -// -// Returns 0 for an error or the constructed node. -// -TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, const TSourceLoc& line, bool subset) -{ - TIntermTyped* newNode; - TOperator basicOp; - - // - // First, convert types as needed. - // - switch (op) { - case EOpConstructVec2: - case EOpConstructVec3: - case EOpConstructVec4: - case EOpConstructMat2: - case EOpConstructMat3: - case EOpConstructMat4: - case EOpConstructFloat: - basicOp = EOpConstructFloat; - break; - - case EOpConstructIVec2: - case EOpConstructIVec3: - case EOpConstructIVec4: - case EOpConstructInt: - basicOp = EOpConstructInt; - break; - - case EOpConstructBVec2: - case EOpConstructBVec3: - case EOpConstructBVec4: - case EOpConstructBool: - basicOp = EOpConstructBool; - break; - - default: - error(line, "unsupported construction", ""); - recover(); - - return 0; - } - newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable); - if (newNode == 0) { - error(line, "can't convert", "constructor"); - return 0; - } - - // - // Now, if there still isn't an operation to do the construction, and we need one, add one. - // - - // Otherwise, skip out early. - if (subset || (newNode != node && newNode->getType() == *type)) - return newNode; - - // setAggregateOperator will insert a new node for the constructor, as needed. - return intermediate.setAggregateOperator(newNode, op, line); -} - -// This function tests for the type of the parameters to the structures constructors. Raises -// an error message if the expected type does not match the parameter passed to the constructor. -// -// Returns 0 for an error or the input node itself if the expected and the given parameter types match. -// -TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, const TSourceLoc& line, bool subset) -{ - if (*type == node->getAsTyped()->getType()) { - if (subset) - return node->getAsTyped(); - else - return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line); - } else { - std::stringstream extraInfoStream; - extraInfoStream << "cannot convert parameter " << paramCount - << " from '" << node->getAsTyped()->getType().getBasicString() - << "' to '" << type->getBasicString() << "'"; - std::string extraInfo = extraInfoStream.str(); - error(line, "", "constructor", extraInfo.c_str()); - recover(); - } - - return 0; -} - -// -// This function returns the tree representation for the vector field(s) being accessed from contant vector. -// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is -// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol -// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of -// a constant matrix. -// -TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line) -{ - TIntermTyped* typedNode; - TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); - - ConstantUnion *unionArray; - if (tempConstantNode) { - unionArray = tempConstantNode->getUnionArrayPointer(); - - if (!unionArray) { - return node; - } - } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error - error(line, "Cannot offset into the vector", "Error"); - recover(); - - return 0; - } - - ConstantUnion* constArray = new ConstantUnion[fields.num]; - - for (int i = 0; i < fields.num; i++) { - if (fields.offsets[i] >= node->getType().getNominalSize()) { - std::stringstream extraInfoStream; - extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'"; - std::string extraInfo = extraInfoStream.str(); - error(line, "", "[", extraInfo.c_str()); - recover(); - fields.offsets[i] = 0; - } - - constArray[i] = unionArray[fields.offsets[i]]; - - } - typedNode = intermediate.addConstantUnion(constArray, node->getType(), line); - return typedNode; -} - -// -// This function returns the column being accessed from a constant matrix. The values are retrieved from -// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input -// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a -// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure) -// -TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line) -{ - TIntermTyped* typedNode; - TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); - - if (index >= node->getType().getNominalSize()) { - std::stringstream extraInfoStream; - extraInfoStream << "matrix field selection out of range '" << index << "'"; - std::string extraInfo = extraInfoStream.str(); - error(line, "", "[", extraInfo.c_str()); - recover(); - index = 0; - } - - if (tempConstantNode) { - ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); - int size = tempConstantNode->getType().getNominalSize(); - typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line); - } else { - error(line, "Cannot offset into the matrix", "Error"); - recover(); - - return 0; - } - - return typedNode; -} - - -// -// This function returns an element of an array accessed from a constant array. The values are retrieved from -// the symbol table and parse-tree is built for the type of the element. The input -// to the function could either be a symbol node (a[0] where a is a constant array)that represents a -// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure) -// -TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line) -{ - TIntermTyped* typedNode; - TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); - TType arrayElementType = node->getType(); - arrayElementType.clearArrayness(); - - if (index >= node->getType().getArraySize()) { - std::stringstream extraInfoStream; - extraInfoStream << "array field selection out of range '" << index << "'"; - std::string extraInfo = extraInfoStream.str(); - error(line, "", "[", extraInfo.c_str()); - recover(); - index = 0; - } - - if (tempConstantNode) { - size_t arrayElementSize = arrayElementType.getObjectSize(); - ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); - typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line); - } else { - error(line, "Cannot offset into the array", "Error"); - recover(); - - return 0; - } - - return typedNode; -} - - -// -// This function returns the value of a particular field inside a constant structure from the symbol table. -// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr -// function and returns the parse-tree with the values of the embedded/nested struct. -// -TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, const TSourceLoc& line) -{ - const TFieldList& fields = node->getType().getStruct()->fields(); - - size_t instanceSize = 0; - for (size_t index = 0; index < fields.size(); ++index) { - if (fields[index]->name() == identifier) { - break; - } else { - instanceSize += fields[index]->type()->getObjectSize(); - } - } - - TIntermTyped* typedNode = 0; - TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); - if (tempConstantNode) { - ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer(); - - typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function - } else { - error(line, "Cannot offset into the structure", "Error"); - recover(); - - return 0; - } - - return typedNode; -} - -bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier) -{ - ++structNestingLevel; - - // Embedded structure definitions are not supported per GLSL ES spec. - // They aren't allowed in GLSL either, but we need to detect this here - // so we don't rely on the GLSL compiler to catch it. - if (structNestingLevel > 1) { - error(line, "", "Embedded struct definitions are not allowed"); - return true; - } - - return false; -} - -void TParseContext::exitStructDeclaration() -{ - --structNestingLevel; -} - -namespace { - -const int kWebGLMaxStructNesting = 4; - -} // namespace - -bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field) -{ - if (!isWebGLBasedSpec(shaderSpec)) { - return false; - } - - if (field.type()->getBasicType() != EbtStruct) { - return false; - } - - // We're already inside a structure definition at this point, so add - // one to the field's struct nesting. - if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) { - std::stringstream reasonStream; - reasonStream << "Reference of struct type " - << field.type()->getStruct()->name().c_str() - << " exceeds maximum allowed nesting level of " - << kWebGLMaxStructNesting; - std::string reason = reasonStream.str(); - error(line, reason.c_str(), field.name().c_str(), ""); - return true; - } - - return false; -} - -// -// Parse an array index expression -// -TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression) -{ - TIntermTyped *indexedExpression = NULL; - - if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector()) - { - if (baseExpression->getAsSymbolNode()) - { - error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str()); - } - else - { - error(location, " left of '[' is not of type array, matrix, or vector ", "expression"); - } - recover(); - } - - if (indexExpression->getQualifier() == EvqConst) - { - int index = indexExpression->getAsConstantUnion()->getIConst(0); - if (index < 0) - { - std::stringstream infoStream; - infoStream << index; - std::string info = infoStream.str(); - error(location, "negative index", info.c_str()); - recover(); - index = 0; - } - if (baseExpression->getType().getQualifier() == EvqConst) - { - if (baseExpression->isArray()) - { - // constant folding for arrays - indexedExpression = addConstArrayNode(index, baseExpression, location); - } - else if (baseExpression->isVector()) - { - // constant folding for vectors - TVectorFields fields; - fields.num = 1; - fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array - indexedExpression = addConstVectorNode(fields, baseExpression, location); - } - else if (baseExpression->isMatrix()) - { - // constant folding for matrices - indexedExpression = addConstMatrixNode(index, baseExpression, location); - } - } - else - { - if (baseExpression->isArray()) - { - if (index >= baseExpression->getType().getArraySize()) - { - std::stringstream extraInfoStream; - extraInfoStream << "array index out of range '" << index << "'"; - std::string extraInfo = extraInfoStream.str(); - error(location, "", "[", extraInfo.c_str()); - recover(); - index = baseExpression->getType().getArraySize() - 1; - } - else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers")) - { - error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled"); - recover(); - index = 0; - } - } - else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index) - { - std::stringstream extraInfoStream; - extraInfoStream << "field selection out of range '" << index << "'"; - std::string extraInfo = extraInfoStream.str(); - error(location, "", "[", extraInfo.c_str()); - recover(); - index = baseExpression->getType().getNominalSize() - 1; - } - - indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index); - indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location); - } - } - else - { - indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location); - } - - if (indexedExpression == 0) - { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setFConst(0.0f); - indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location); - } - else if (baseExpression->isArray()) - { - const TType &baseType = baseExpression->getType(); - if (baseType.getStruct()) - { - TType copyOfType(baseType.getStruct()); - indexedExpression->setType(copyOfType); - } - else - { - indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->isMatrix())); - } - - if (baseExpression->getType().getQualifier() == EvqConst) - { - indexedExpression->getTypePointer()->setQualifier(EvqConst); - } - } - else if (baseExpression->isMatrix()) - { - TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary; - indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getNominalSize())); - } - else if (baseExpression->isVector()) - { - TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary; - indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier)); - } - else - { - indexedExpression->setType(baseExpression->getType()); - } - - return indexedExpression; -} - -// -// Parse an array of strings using yyparse. -// -// Returns 0 for success. -// -int PaParseStrings(size_t count, const char* const string[], const int length[], - TParseContext* context) { - if ((count == 0) || (string == NULL)) - return 1; - - if (glslang_initialize(context)) - return 1; - - int error = glslang_scan(count, string, length, context); - if (!error) - error = glslang_parse(context); - - glslang_finalize(context); - - return (error == 0) && (context->numErrors() == 0) ? 0 : 1; -} - - - diff --git a/src/3rdparty/angle/src/compiler/ParseHelper.h b/src/3rdparty/angle/src/compiler/ParseHelper.h deleted file mode 100644 index c2b3c3f7ec..0000000000 --- a/src/3rdparty/angle/src/compiler/ParseHelper.h +++ /dev/null @@ -1,134 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -#ifndef _PARSER_HELPER_INCLUDED_ -#define _PARSER_HELPER_INCLUDED_ - -#include "compiler/Diagnostics.h" -#include "compiler/DirectiveHandler.h" -#include "compiler/localintermediate.h" -#include "compiler/preprocessor/Preprocessor.h" -#include "compiler/ShHandle.h" -#include "compiler/SymbolTable.h" - -struct TMatrixFields { - bool wholeRow; - bool wholeCol; - int row; - int col; -}; - -// -// The following are extra variables needed during parsing, grouped together so -// they can be passed to the parser without needing a global. -// -struct TParseContext { - TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, ShShaderType type, ShShaderSpec spec, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) : - intermediate(interm), - symbolTable(symt), - shaderType(type), - shaderSpec(spec), - compileOptions(options), - sourcePath(sourcePath), - treeRoot(0), - loopNestingLevel(0), - structNestingLevel(0), - currentFunctionType(NULL), - functionReturnsValue(false), - checksPrecisionErrors(checksPrecErrors), - diagnostics(is), - directiveHandler(ext, diagnostics), - preprocessor(&diagnostics, &directiveHandler), - scanner(NULL) { } - TIntermediate& intermediate; // to hold and build a parse tree - TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed - ShShaderType shaderType; // vertex or fragment language (future: pack or unpack) - ShShaderSpec shaderSpec; // The language specification compiler conforms to - GLES2 or WebGL. - int compileOptions; - const char* sourcePath; // Path of source file or NULL. - TIntermNode* treeRoot; // root of parse tree being created - int loopNestingLevel; // 0 if outside all loops - int structNestingLevel; // incremented while parsing a struct declaration - const TType* currentFunctionType; // the return type of the function that's currently being parsed - bool functionReturnsValue; // true if a non-void function has a return - bool checksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit. - bool fragmentPrecisionHigh; // true if highp precision is supported in the fragment language. - TString HashErrMsg; - TDiagnostics diagnostics; - TDirectiveHandler directiveHandler; - pp::Preprocessor preprocessor; - void* scanner; - - int numErrors() const { return diagnostics.numErrors(); } - TInfoSink& infoSink() { return diagnostics.infoSink(); } - void error(const TSourceLoc& loc, const char *reason, const char* token, - const char* extraInfo=""); - void warning(const TSourceLoc& loc, const char* reason, const char* token, - const char* extraInfo=""); - void trace(const char* str); - void recover(); - - bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc& line); - bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, const TSourceLoc& line); - - bool reservedErrorCheck(const TSourceLoc& line, const TString& identifier); - void assignError(const TSourceLoc& line, const char* op, TString left, TString right); - void unaryOpError(const TSourceLoc& line, const char* op, TString operand); - void binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right); - bool precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type); - bool lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped*); - bool constErrorCheck(TIntermTyped* node); - bool integerErrorCheck(TIntermTyped* node, const char* token); - bool globalErrorCheck(const TSourceLoc& line, bool global, const char* token); - bool constructorErrorCheck(const TSourceLoc& line, TIntermNode*, TFunction&, TOperator, TType*); - bool arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size); - bool arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type); - bool arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type); - bool arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable); - bool voidErrorCheck(const TSourceLoc&, const TString&, const TPublicType&); - bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*); - bool boolErrorCheck(const TSourceLoc&, const TPublicType&); - bool samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason); - bool structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType); - bool parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type); - bool nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array); - bool nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable); - bool paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type); - bool extensionErrorCheck(const TSourceLoc& line, const TString&); - - const TPragma& pragma() const { return directiveHandler.pragma(); } - const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); } - bool supportsExtension(const char* extension); - bool isExtensionEnabled(const char* extension) const; - - bool containsSampler(TType& type); - bool areAllChildConst(TIntermAggregate* aggrNode); - const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, bool *builtIn = 0); - bool executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType, - TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0); - - TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&); - TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type); - TIntermTyped* constructStruct(TIntermNode*, TType*, int, const TSourceLoc&, bool subset); - TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, const TSourceLoc&, bool subset); - TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&); - TIntermTyped* addConstMatrixNode(int , TIntermTyped*, const TSourceLoc&); - TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line); - TIntermTyped* addConstStruct(TString& , TIntermTyped*, const TSourceLoc&); - TIntermTyped* addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression); - - // Performs an error check for embedded struct declarations. - // Returns true if an error was raised due to the declaration of - // this struct. - bool enterStructDeclaration(const TSourceLoc& line, const TString& identifier); - void exitStructDeclaration(); - - bool structNestingErrorCheck(const TSourceLoc& line, const TField& field); -}; - -int PaParseStrings(size_t count, const char* const string[], const int length[], - TParseContext* context); - -#endif // _PARSER_HELPER_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/PoolAlloc.cpp b/src/3rdparty/angle/src/compiler/PoolAlloc.cpp deleted file mode 100644 index eb993567b3..0000000000 --- a/src/3rdparty/angle/src/compiler/PoolAlloc.cpp +++ /dev/null @@ -1,294 +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. -// - -#include "compiler/PoolAlloc.h" - -#ifndef _MSC_VER -#include -#endif -#include - -#include "common/angleutils.h" -#include "compiler/InitializeGlobals.h" -#include "compiler/osinclude.h" - -OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX; - -bool InitializePoolIndex() -{ - assert(PoolIndex == OS_INVALID_TLS_INDEX); - - PoolIndex = OS_AllocTLSIndex(); - return PoolIndex != OS_INVALID_TLS_INDEX; -} - -void FreePoolIndex() -{ - assert(PoolIndex != OS_INVALID_TLS_INDEX); - - OS_FreeTLSIndex(PoolIndex); - PoolIndex = OS_INVALID_TLS_INDEX; -} - -TPoolAllocator* GetGlobalPoolAllocator() -{ - assert(PoolIndex != OS_INVALID_TLS_INDEX); - return static_cast(OS_GetTLSValue(PoolIndex)); -} - -void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator) -{ - assert(PoolIndex != OS_INVALID_TLS_INDEX); - OS_SetTLSValue(PoolIndex, poolAllocator); -} - -// -// Implement the functionality of the TPoolAllocator class, which -// is documented in PoolAlloc.h. -// -TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) : - pageSize(growthIncrement), - alignment(allocationAlignment), - freeList(0), - inUseList(0), - numCalls(0), - totalBytes(0) -{ - // - // Don't allow page sizes we know are smaller than all common - // OS page sizes. - // - if (pageSize < 4*1024) - pageSize = 4*1024; - - // - // A large currentPageOffset indicates a new page needs to - // be obtained to allocate memory. - // - currentPageOffset = pageSize; - - // - // Adjust alignment to be at least pointer aligned and - // power of 2. - // - size_t minAlign = sizeof(void*); - alignment &= ~(minAlign - 1); - if (alignment < minAlign) - alignment = minAlign; - size_t a = 1; - while (a < alignment) - a <<= 1; - alignment = a; - alignmentMask = a - 1; - - // - // Align header skip - // - headerSkip = minAlign; - if (headerSkip < sizeof(tHeader)) { - headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask; - } -} - -TPoolAllocator::~TPoolAllocator() -{ - while (inUseList) { - tHeader* next = inUseList->nextPage; - inUseList->~tHeader(); - delete [] reinterpret_cast(inUseList); - inUseList = next; - } - - // We should not check the guard blocks - // here, because we did it already when the block was - // placed into the free list. - // - while (freeList) { - tHeader* next = freeList->nextPage; - delete [] reinterpret_cast(freeList); - freeList = next; - } -} - -// Support MSVC++ 6.0 -const unsigned char TAllocation::guardBlockBeginVal = 0xfb; -const unsigned char TAllocation::guardBlockEndVal = 0xfe; -const unsigned char TAllocation::userDataFill = 0xcd; - -#ifdef GUARD_BLOCKS - const size_t TAllocation::guardBlockSize = 16; -#else - const size_t TAllocation::guardBlockSize = 0; -#endif - -// -// Check a single guard block for damage -// -void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const -{ -#ifdef GUARD_BLOCKS - for (size_t x = 0; x < guardBlockSize; x++) { - if (blockMem[x] != val) { - char assertMsg[80]; - - // We don't print the assert message. It's here just to be helpful. -#if defined(_MSC_VER) - snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %Iu byte allocation at 0x%p\n", - locText, size, data()); -#else - snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n", - locText, size, data()); -#endif - assert(0 && "PoolAlloc: Damage in guard block"); - } - } -#endif -} - - -void TPoolAllocator::push() -{ - tAllocState state = { currentPageOffset, inUseList }; - - stack.push_back(state); - - // - // Indicate there is no current page to allocate from. - // - currentPageOffset = pageSize; -} - -// -// Do a mass-deallocation of all the individual allocations -// that have occurred since the last push(), or since the -// last pop(), or since the object's creation. -// -// The deallocated pages are saved for future allocations. -// -void TPoolAllocator::pop() -{ - if (stack.size() < 1) - return; - - tHeader* page = stack.back().page; - currentPageOffset = stack.back().offset; - - while (inUseList != page) { - // invoke destructor to free allocation list - inUseList->~tHeader(); - - tHeader* nextInUse = inUseList->nextPage; - if (inUseList->pageCount > 1) - delete [] reinterpret_cast(inUseList); - else { - inUseList->nextPage = freeList; - freeList = inUseList; - } - inUseList = nextInUse; - } - - stack.pop_back(); -} - -// -// Do a mass-deallocation of all the individual allocations -// that have occurred. -// -void TPoolAllocator::popAll() -{ - while (stack.size() > 0) - pop(); -} - -void* TPoolAllocator::allocate(size_t numBytes) -{ - // - // Just keep some interesting statistics. - // - ++numCalls; - totalBytes += numBytes; - - // If we are using guard blocks, all allocations are bracketed by - // them: [guardblock][allocation][guardblock]. numBytes is how - // much memory the caller asked for. allocationSize is the total - // size including guard blocks. In release build, - // guardBlockSize=0 and this all gets optimized away. - size_t allocationSize = TAllocation::allocationSize(numBytes); - // Detect integer overflow. - if (allocationSize < numBytes) - return 0; - - // - // Do the allocation, most likely case first, for efficiency. - // This step could be moved to be inline sometime. - // - if (allocationSize <= pageSize - currentPageOffset) { - // - // Safe to allocate from currentPageOffset. - // - unsigned char* memory = reinterpret_cast(inUseList) + currentPageOffset; - currentPageOffset += allocationSize; - currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask; - - return initializeAllocation(inUseList, memory, numBytes); - } - - if (allocationSize > pageSize - headerSkip) { - // - // Do a multi-page allocation. Don't mix these with the others. - // The OS is efficient and allocating and free-ing multiple pages. - // - size_t numBytesToAlloc = allocationSize + headerSkip; - // Detect integer overflow. - if (numBytesToAlloc < allocationSize) - return 0; - - tHeader* memory = reinterpret_cast(::new char[numBytesToAlloc]); - if (memory == 0) - return 0; - - // Use placement-new to initialize header - new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize); - inUseList = memory; - - currentPageOffset = pageSize; // make next allocation come from a new page - - // No guard blocks for multi-page allocations (yet) - return reinterpret_cast(reinterpret_cast(memory) + headerSkip); - } - - // - // Need a simple page to allocate from. - // - tHeader* memory; - if (freeList) { - memory = freeList; - freeList = freeList->nextPage; - } else { - memory = reinterpret_cast(::new char[pageSize]); - if (memory == 0) - return 0; - } - - // Use placement-new to initialize header - new(memory) tHeader(inUseList, 1); - inUseList = memory; - - unsigned char* ret = reinterpret_cast(inUseList) + headerSkip; - currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask; - - return initializeAllocation(inUseList, ret, numBytes); -} - - -// -// Check all allocations in a list for damage by calling check on each. -// -void TAllocation::checkAllocList() const -{ - for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc) - alloc->check(); -} diff --git a/src/3rdparty/angle/src/compiler/PoolAlloc.h b/src/3rdparty/angle/src/compiler/PoolAlloc.h deleted file mode 100644 index edd249c4d3..0000000000 --- a/src/3rdparty/angle/src/compiler/PoolAlloc.h +++ /dev/null @@ -1,300 +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. -// - -#ifndef _POOLALLOC_INCLUDED_ -#define _POOLALLOC_INCLUDED_ - -#ifdef _DEBUG -#define GUARD_BLOCKS // define to enable guard block sanity checking -#endif - -// -// This header defines an allocator that can be used to efficiently -// allocate a large number of small requests for heap memory, with the -// intention that they are not individually deallocated, but rather -// collectively deallocated at one time. -// -// This simultaneously -// -// * Makes each individual allocation much more efficient; the -// typical allocation is trivial. -// * Completely avoids the cost of doing individual deallocation. -// * Saves the trouble of tracking down and plugging a large class of leaks. -// -// Individual classes can use this allocator by supplying their own -// new and delete methods. -// -// STL containers can use this allocator by using the pool_allocator -// class as the allocator (second) template argument. -// - -#include -#include -#include - -// If we are using guard blocks, we must track each indivual -// allocation. If we aren't using guard blocks, these -// never get instantiated, so won't have any impact. -// - -class TAllocation { -public: - TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) : - size(size), mem(mem), prevAlloc(prev) { - // Allocations are bracketed: - // [allocationHeader][initialGuardBlock][userData][finalGuardBlock] - // This would be cleaner with if (guardBlockSize)..., but that - // makes the compiler print warnings about 0 length memsets, - // even with the if() protecting them. -#ifdef GUARD_BLOCKS - memset(preGuard(), guardBlockBeginVal, guardBlockSize); - memset(data(), userDataFill, size); - memset(postGuard(), guardBlockEndVal, guardBlockSize); -#endif - } - - void check() const { - checkGuardBlock(preGuard(), guardBlockBeginVal, "before"); - checkGuardBlock(postGuard(), guardBlockEndVal, "after"); - } - - void checkAllocList() const; - - // Return total size needed to accomodate user buffer of 'size', - // plus our tracking data. - inline static size_t allocationSize(size_t size) { - return size + 2 * guardBlockSize + headerSize(); - } - - // Offset from surrounding buffer to get to user data buffer. - inline static unsigned char* offsetAllocation(unsigned char* m) { - return m + guardBlockSize + headerSize(); - } - -private: - void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const; - - // Find offsets to pre and post guard blocks, and user data buffer - unsigned char* preGuard() const { return mem + headerSize(); } - unsigned char* data() const { return preGuard() + guardBlockSize; } - unsigned char* postGuard() const { return data() + size; } - - size_t size; // size of the user data area - unsigned char* mem; // beginning of our allocation (pts to header) - TAllocation* prevAlloc; // prior allocation in the chain - - // Support MSVC++ 6.0 - const static unsigned char guardBlockBeginVal; - const static unsigned char guardBlockEndVal; - const static unsigned char userDataFill; - - const static size_t guardBlockSize; -#ifdef GUARD_BLOCKS - inline static size_t headerSize() { return sizeof(TAllocation); } -#else - inline static size_t headerSize() { return 0; } -#endif -}; - -// -// There are several stacks. One is to track the pushing and popping -// of the user, and not yet implemented. The others are simply a -// repositories of free pages or used pages. -// -// Page stacks are linked together with a simple header at the beginning -// of each allocation obtained from the underlying OS. Multi-page allocations -// are returned to the OS. Individual page allocations are kept for future -// re-use. -// -// The "page size" used is not, nor must it match, the underlying OS -// page size. But, having it be about that size or equal to a set of -// pages is likely most optimal. -// -class TPoolAllocator { -public: - TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16); - - // - // Don't call the destructor just to free up the memory, call pop() - // - ~TPoolAllocator(); - - // - // Call push() to establish a new place to pop memory too. Does not - // have to be called to get things started. - // - void push(); - - // - // Call pop() to free all memory allocated since the last call to push(), - // or if no last call to push, frees all memory since first allocation. - // - void pop(); - - // - // Call popAll() to free all memory allocated. - // - void popAll(); - - // - // Call allocate() to actually acquire memory. Returns 0 if no memory - // available, otherwise a properly aligned pointer to 'numBytes' of memory. - // - void* allocate(size_t numBytes); - - // - // There is no deallocate. The point of this class is that - // deallocation can be skipped by the user of it, as the model - // of use is to simultaneously deallocate everything at once - // by calling pop(), and to not have to solve memory leak problems. - // - -protected: - friend struct tHeader; - - struct tHeader { - tHeader(tHeader* nextPage, size_t pageCount) : - nextPage(nextPage), - pageCount(pageCount) -#ifdef GUARD_BLOCKS - , lastAllocation(0) -#endif - { } - - ~tHeader() { -#ifdef GUARD_BLOCKS - if (lastAllocation) - lastAllocation->checkAllocList(); -#endif - } - - tHeader* nextPage; - size_t pageCount; -#ifdef GUARD_BLOCKS - TAllocation* lastAllocation; -#endif - }; - - struct tAllocState { - size_t offset; - tHeader* page; - }; - typedef std::vector tAllocStack; - - // Track allocations if and only if we're using guard blocks - void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) { -#ifdef GUARD_BLOCKS - new(memory) TAllocation(numBytes, memory, block->lastAllocation); - block->lastAllocation = reinterpret_cast(memory); -#endif - // This is optimized entirely away if GUARD_BLOCKS is not defined. - return TAllocation::offsetAllocation(memory); - } - - size_t pageSize; // granularity of allocation from the OS - size_t alignment; // all returned allocations will be aligned at - // this granularity, which will be a power of 2 - size_t alignmentMask; - size_t headerSkip; // amount of memory to skip to make room for the - // header (basically, size of header, rounded - // up to make it aligned - size_t currentPageOffset; // next offset in top of inUseList to allocate from - tHeader* freeList; // list of popped memory - tHeader* inUseList; // list of all memory currently being used - tAllocStack stack; // stack of where to allocate from, to partition pool - - int numCalls; // just an interesting statistic - size_t totalBytes; // just an interesting statistic -private: - TPoolAllocator& operator=(const TPoolAllocator&); // dont allow assignment operator - TPoolAllocator(const TPoolAllocator&); // dont allow default copy constructor -}; - - -// -// There could potentially be many pools with pops happening at -// different times. But a simple use is to have a global pop -// with everyone using the same global allocator. -// -extern TPoolAllocator* GetGlobalPoolAllocator(); -extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator); - -// -// This STL compatible allocator is intended to be used as the allocator -// parameter to templatized STL containers, like vector and map. -// -// It will use the pools for allocation, and not -// do any deallocation, but will still do destruction. -// -template -class pool_allocator { -public: - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& const_reference; - typedef T value_type; - - template - struct rebind { - typedef pool_allocator other; - }; - pointer address(reference x) const { return &x; } - const_pointer address(const_reference x) const { return &x; } - - pool_allocator() : allocator(GetGlobalPoolAllocator()) { } - pool_allocator(TPoolAllocator& a) : allocator(&a) { } - pool_allocator(const pool_allocator& p) : allocator(p.allocator) { } - - template - pool_allocator& operator=(const pool_allocator& p) { - allocator = p.allocator; - return *this; - } - - template - pool_allocator(const pool_allocator& p) : allocator(&p.getAllocator()) { } - -#if defined(__SUNPRO_CC) && !defined(_RWSTD_ALLOCATOR) - // libCStd on some platforms have a different allocate/deallocate interface. - // Caller pre-bakes sizeof(T) into 'n' which is the number of bytes to be - // allocated, not the number of elements. - void* allocate(size_type n) { - return getAllocator().allocate(n); - } - void* allocate(size_type n, const void*) { - return getAllocator().allocate(n); - } - void deallocate(void*, size_type) {} -#else - pointer allocate(size_type n) { - return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); - } - pointer allocate(size_type n, const void*) { - return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); - } - void deallocate(pointer, size_type) {} -#endif // _RWSTD_ALLOCATOR - - void construct(pointer p, const T& val) { new ((void *)p) T(val); } - void destroy(pointer p) { p->T::~T(); } - - bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); } - bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); } - - size_type max_size() const { return static_cast(-1) / sizeof(T); } - size_type max_size(int size) const { return static_cast(-1) / size; } - - void setAllocator(TPoolAllocator* a) { allocator = a; } - TPoolAllocator& getAllocator() const { return *allocator; } - -protected: - TPoolAllocator* allocator; -}; - -#endif // _POOLALLOC_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/Pragma.h b/src/3rdparty/angle/src/compiler/Pragma.h deleted file mode 100644 index 2f744123b8..0000000000 --- a/src/3rdparty/angle/src/compiler/Pragma.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_PRAGMA_H_ -#define COMPILER_PRAGMA_H_ - -struct TPragma { - // By default optimization is turned on and debug is turned off. - TPragma() : optimize(true), debug(false) { } - TPragma(bool o, bool d) : optimize(o), debug(d) { } - - bool optimize; - bool debug; -}; - -#endif // COMPILER_PRAGMA_H_ diff --git a/src/3rdparty/angle/src/compiler/QualifierAlive.cpp b/src/3rdparty/angle/src/compiler/QualifierAlive.cpp deleted file mode 100644 index 92a6874eb7..0000000000 --- a/src/3rdparty/angle/src/compiler/QualifierAlive.cpp +++ /dev/null @@ -1,58 +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. -// - -#include "compiler/intermediate.h" - -class TAliveTraverser : public TIntermTraverser { -public: - TAliveTraverser(TQualifier q) : TIntermTraverser(true, false, false, true), found(false), qualifier(q) - { - } - - bool wasFound() { return found; } - -protected: - bool found; - TQualifier qualifier; - - void visitSymbol(TIntermSymbol*); - bool visitSelection(Visit, TIntermSelection*); -}; - -// -// Report whether or not a variable of the given qualifier type -// is guaranteed written. Not always possible to determine if -// it is written conditionally. -// -// ?? It does not do this well yet, this is just a place holder -// that simply determines if it was reference at all, anywhere. -// -bool QualifierWritten(TIntermNode* node, TQualifier qualifier) -{ - TAliveTraverser it(qualifier); - - if (node) - node->traverse(&it); - - return it.wasFound(); -} - -void TAliveTraverser::visitSymbol(TIntermSymbol* node) -{ - // - // If it's what we're looking for, record it. - // - if (node->getQualifier() == qualifier) - found = true; -} - -bool TAliveTraverser::visitSelection(Visit preVisit, TIntermSelection* node) -{ - if (wasFound()) - return false; - - return true; -} diff --git a/src/3rdparty/angle/src/compiler/QualifierAlive.h b/src/3rdparty/angle/src/compiler/QualifierAlive.h deleted file mode 100644 index 872a06f721..0000000000 --- a/src/3rdparty/angle/src/compiler/QualifierAlive.h +++ /dev/null @@ -1,7 +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. -// - -bool QualifierWritten(TIntermNode* root, TQualifier); diff --git a/src/3rdparty/angle/src/compiler/RemoveTree.cpp b/src/3rdparty/angle/src/compiler/RemoveTree.cpp deleted file mode 100644 index a4b8c1e63e..0000000000 --- a/src/3rdparty/angle/src/compiler/RemoveTree.cpp +++ /dev/null @@ -1,77 +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. -// - -#include "compiler/intermediate.h" -#include "compiler/RemoveTree.h" - -// -// Code to recursively delete the intermediate tree. -// - -class RemoveTree : public TIntermTraverser -{ -public: - RemoveTree() : TIntermTraverser(false, false, true) - { - } - -protected: - void visitSymbol(TIntermSymbol*); - void visitConstantUnion(TIntermConstantUnion*); - bool visitBinary(Visit visit, TIntermBinary*); - bool visitUnary(Visit visit, TIntermUnary*); - bool visitSelection(Visit visit, TIntermSelection*); - bool visitAggregate(Visit visit, TIntermAggregate*); -}; - -void RemoveTree::visitSymbol(TIntermSymbol* node) -{ - delete node; -} - -bool RemoveTree::visitBinary(Visit visit, TIntermBinary* node) -{ - delete node; - - return true; -} - -bool RemoveTree::visitUnary(Visit visit, TIntermUnary* node) -{ - delete node; - - return true; -} - -bool RemoveTree::visitAggregate(Visit visit, TIntermAggregate* node) -{ - delete node; - - return true; -} - -bool RemoveTree::visitSelection(Visit visit, TIntermSelection* node) -{ - delete node; - - return true; -} - -void RemoveTree::visitConstantUnion(TIntermConstantUnion* node) -{ - delete node; -} - -// -// Entry point. -// -void RemoveAllTreeNodes(TIntermNode* root) -{ - RemoveTree it; - - root->traverse(&it); -} - diff --git a/src/3rdparty/angle/src/compiler/RemoveTree.h b/src/3rdparty/angle/src/compiler/RemoveTree.h deleted file mode 100644 index 97a821679c..0000000000 --- a/src/3rdparty/angle/src/compiler/RemoveTree.h +++ /dev/null @@ -1,7 +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. -// - -void RemoveAllTreeNodes(TIntermNode*); diff --git a/src/3rdparty/angle/src/compiler/RenameFunction.h b/src/3rdparty/angle/src/compiler/RenameFunction.h deleted file mode 100644 index 3908bfddb8..0000000000 --- a/src/3rdparty/angle/src/compiler/RenameFunction.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_RENAME_FUNCTION -#define COMPILER_RENAME_FUNCTION - -#include "compiler/intermediate.h" - -// -// Renames a function, including its declaration and any calls to it. -// -class RenameFunction : public TIntermTraverser -{ -public: - RenameFunction(const TString& oldFunctionName, const TString& newFunctionName) - : TIntermTraverser(true, false, false) - , mOldFunctionName(oldFunctionName) - , mNewFunctionName(newFunctionName) {} - - virtual bool visitAggregate(Visit visit, TIntermAggregate* node) - { - TOperator op = node->getOp(); - if ((op == EOpFunction || op == EOpFunctionCall) && node->getName() == mOldFunctionName) - node->setName(mNewFunctionName); - return true; - } - -private: - const TString mOldFunctionName; - const TString mNewFunctionName; -}; - -#endif // COMPILER_RENAME_FUNCTION diff --git a/src/3rdparty/angle/src/compiler/SearchSymbol.cpp b/src/3rdparty/angle/src/compiler/SearchSymbol.cpp deleted file mode 100644 index 9368f1a4fa..0000000000 --- a/src/3rdparty/angle/src/compiler/SearchSymbol.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. -// -// SearchSymbol is an AST traverser to detect the use of a given symbol name -// - -#include "compiler/SearchSymbol.h" - -#include "compiler/InfoSink.h" -#include "compiler/OutputHLSL.h" - -namespace sh -{ -SearchSymbol::SearchSymbol(const TString &symbol) : mSymbol(symbol) -{ - match = false; -} - -void SearchSymbol::traverse(TIntermNode *node) -{ - node->traverse(this); -} - -void SearchSymbol::visitSymbol(TIntermSymbol *symbolNode) -{ - if (symbolNode->getSymbol() == mSymbol) - { - match = true; - } -} - -bool SearchSymbol::foundMatch() const -{ - return match; -} -} diff --git a/src/3rdparty/angle/src/compiler/SearchSymbol.h b/src/3rdparty/angle/src/compiler/SearchSymbol.h deleted file mode 100644 index 6bc0b90feb..0000000000 --- a/src/3rdparty/angle/src/compiler/SearchSymbol.h +++ /dev/null @@ -1,33 +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. -// -// SearchSymbol is an AST traverser to detect the use of a given symbol name -// - -#ifndef COMPILER_SEARCHSYMBOL_H_ -#define COMPILER_SEARCHSYMBOL_H_ - -#include "compiler/intermediate.h" -#include "compiler/ParseHelper.h" - -namespace sh -{ -class SearchSymbol : public TIntermTraverser -{ - public: - SearchSymbol(const TString &symbol); - - void traverse(TIntermNode *node); - void visitSymbol(TIntermSymbol *symbolNode); - - bool foundMatch() const; - - protected: - const TString &mSymbol; - bool match; -}; -} - -#endif // COMPILER_SEARCHSYMBOL_H_ diff --git a/src/3rdparty/angle/src/compiler/ShHandle.h b/src/3rdparty/angle/src/compiler/ShHandle.h deleted file mode 100644 index 873580a99c..0000000000 --- a/src/3rdparty/angle/src/compiler/ShHandle.h +++ /dev/null @@ -1,169 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef _SHHANDLE_INCLUDED_ -#define _SHHANDLE_INCLUDED_ - -// -// Machine independent part of the compiler private objects -// sent as ShHandle to the driver. -// -// This should not be included by driver code. -// - -#include "GLSLANG/ShaderLang.h" - -#include "compiler/BuiltInFunctionEmulator.h" -#include "compiler/ExtensionBehavior.h" -#include "compiler/HashNames.h" -#include "compiler/InfoSink.h" -#include "compiler/SymbolTable.h" -#include "compiler/VariableInfo.h" -#include "third_party/compiler/ArrayBoundsClamper.h" - -class LongNameMap; -class TCompiler; -class TDependencyGraph; -class TranslatorHLSL; - -// -// Helper function to identify specs that are based on the WebGL spec, -// like the CSS Shaders spec. -// -bool isWebGLBasedSpec(ShShaderSpec spec); - -// -// The base class used to back handles returned to the driver. -// -class TShHandleBase { -public: - TShHandleBase(); - virtual ~TShHandleBase(); - virtual TCompiler* getAsCompiler() { return 0; } - virtual TranslatorHLSL* getAsTranslatorHLSL() { return 0; } - -protected: - // Memory allocator. Allocates and tracks memory required by the compiler. - // Deallocates all memory when compiler is destructed. - TPoolAllocator allocator; -}; - -// -// The base class for the machine dependent compiler to derive from -// for managing object code from the compile. -// -class TCompiler : public TShHandleBase { -public: - TCompiler(ShShaderType type, ShShaderSpec spec); - virtual ~TCompiler(); - virtual TCompiler* getAsCompiler() { return this; } - - bool Init(const ShBuiltInResources& resources); - bool compile(const char* const shaderStrings[], - size_t numStrings, - int compileOptions); - - // Get results of the last compilation. - TInfoSink& getInfoSink() { return infoSink; } - const TVariableInfoList& getAttribs() const { return attribs; } - const TVariableInfoList& getUniforms() const { return uniforms; } - const TVariableInfoList& getVaryings() const { return varyings; } - int getMappedNameMaxLength() const; - - ShHashFunction64 getHashFunction() const { return hashFunction; } - NameMap& getNameMap() { return nameMap; } - TSymbolTable& getSymbolTable() { return symbolTable; } - -protected: - ShShaderType getShaderType() const { return shaderType; } - ShShaderSpec getShaderSpec() const { return shaderSpec; } - // Initialize symbol-table with built-in symbols. - bool InitBuiltInSymbolTable(const ShBuiltInResources& resources); - // Clears the results from the previous compilation. - void clearResults(); - // Return true if function recursion is detected or call depth exceeded. - bool detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth); - // Rewrites a shader's intermediate tree according to the CSS Shaders spec. - void rewriteCSSShader(TIntermNode* root); - // Returns true if the given shader does not exceed the minimum - // functionality mandated in GLSL 1.0 spec Appendix A. - bool validateLimitations(TIntermNode* root); - // Collect info for all attribs, uniforms, varyings. - void collectVariables(TIntermNode* root); - // Map long variable names into shorter ones. - void mapLongVariableNames(TIntermNode* root); - // Translate to object code. - virtual void translate(TIntermNode* root) = 0; - // Returns true if, after applying the packing rules in the GLSL 1.017 spec - // Appendix A, section 7, the shader does not use too many uniforms. - bool enforcePackingRestrictions(); - // Returns true if the shader passes the restrictions that aim to prevent timing attacks. - bool enforceTimingRestrictions(TIntermNode* root, bool outputGraph); - // Returns true if the shader does not use samplers. - bool enforceVertexShaderTimingRestrictions(TIntermNode* root); - // Returns true if the shader does not use sampler dependent values to affect control - // flow or in operations whose time can depend on the input values. - bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph); - // Return true if the maximum expression complexity below the limit. - bool limitExpressionComplexity(TIntermNode* root); - // Get built-in extensions with default behavior. - const TExtensionBehavior& getExtensionBehavior() const; - // Get the resources set by InitBuiltInSymbolTable - const ShBuiltInResources& getResources() const; - - const ArrayBoundsClamper& getArrayBoundsClamper() const; - ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const; - const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const; - -private: - ShShaderType shaderType; - ShShaderSpec shaderSpec; - - int maxUniformVectors; - int maxExpressionComplexity; - int maxCallStackDepth; - - ShBuiltInResources compileResources; - - // Built-in symbol table for the given language, spec, and resources. - // It is preserved from compile-to-compile. - TSymbolTable symbolTable; - // Built-in extensions with default behavior. - TExtensionBehavior extensionBehavior; - bool fragmentPrecisionHigh; - - ArrayBoundsClamper arrayBoundsClamper; - ShArrayIndexClampingStrategy clampingStrategy; - BuiltInFunctionEmulator builtInFunctionEmulator; - - // Results of compilation. - TInfoSink infoSink; // Output sink. - TVariableInfoList attribs; // Active attributes in the compiled shader. - TVariableInfoList uniforms; // Active uniforms in the compiled shader. - TVariableInfoList varyings; // Varyings in the compiled shader. - - // Cached copy of the ref-counted singleton. - LongNameMap* longNameMap; - - // name hashing. - ShHashFunction64 hashFunction; - NameMap nameMap; -}; - -// -// This is the interface between the machine independent code -// and the machine dependent code. -// -// The machine dependent code should derive from the classes -// above. Then Construct*() and Delete*() will create and -// destroy the machine dependent objects, which contain the -// above machine independent information. -// -TCompiler* ConstructCompiler( - ShShaderType type, ShShaderSpec spec, ShShaderOutput output); -void DeleteCompiler(TCompiler*); - -#endif // _SHHANDLE_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/ShaderLang.cpp deleted file mode 100644 index 42cd5cc5c1..0000000000 --- a/src/3rdparty/angle/src/compiler/ShaderLang.cpp +++ /dev/null @@ -1,387 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// Implement the top-level of interface to the compiler, -// as defined in ShaderLang.h -// - -#include "GLSLANG/ShaderLang.h" - -#include "compiler/InitializeDll.h" -#include "compiler/preprocessor/length_limits.h" -#include "compiler/ShHandle.h" -#include "compiler/TranslatorHLSL.h" -#include "compiler/VariablePacker.h" - -// -// This is the platform independent interface between an OGL driver -// and the shading language compiler. -// - -static bool checkVariableMaxLengths(const ShHandle handle, - size_t expectedValue) -{ - size_t activeUniformLimit = 0; - ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit); - size_t activeAttribLimit = 0; - ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit); - size_t varyingLimit = 0; - ShGetInfo(handle, SH_VARYING_MAX_LENGTH, &varyingLimit); - return (expectedValue == activeUniformLimit && - expectedValue == activeAttribLimit && - expectedValue == varyingLimit); -} - -static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue) -{ - size_t mappedNameMaxLength = 0; - ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength); - return (expectedValue == mappedNameMaxLength); -} - -// -// Driver must call this first, once, before doing any other compiler operations. -// Subsequent calls to this function are no-op. -// -int ShInitialize() -{ - static const bool kInitialized = InitProcess(); - return kInitialized ? 1 : 0; -} - -// -// Cleanup symbol tables -// -int ShFinalize() -{ - DetachProcess(); - return 1; -} - -// -// Initialize built-in resources with minimum expected values. -// -void ShInitBuiltInResources(ShBuiltInResources* resources) -{ - // Constants. - resources->MaxVertexAttribs = 8; - resources->MaxVertexUniformVectors = 128; - resources->MaxVaryingVectors = 8; - resources->MaxVertexTextureImageUnits = 0; - resources->MaxCombinedTextureImageUnits = 8; - resources->MaxTextureImageUnits = 8; - resources->MaxFragmentUniformVectors = 16; - resources->MaxDrawBuffers = 1; - - // Extensions. - resources->OES_standard_derivatives = 0; - resources->OES_EGL_image_external = 0; - resources->ARB_texture_rectangle = 0; - resources->EXT_draw_buffers = 0; - resources->EXT_frag_depth = 0; - - // Disable highp precision in fragment shader by default. - resources->FragmentPrecisionHigh = 0; - - // Disable name hashing by default. - resources->HashFunction = NULL; - - resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC; -} - -// -// Driver calls these to create and destroy compiler objects. -// -ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, - ShShaderOutput output, - const ShBuiltInResources* resources) -{ - TShHandleBase* base = static_cast(ConstructCompiler(type, spec, output)); - TCompiler* compiler = base->getAsCompiler(); - if (compiler == 0) - return 0; - - // Generate built-in symbol table. - if (!compiler->Init(*resources)) { - ShDestruct(base); - return 0; - } - - return reinterpret_cast(base); -} - -void ShDestruct(ShHandle handle) -{ - if (handle == 0) - return; - - TShHandleBase* base = static_cast(handle); - - if (base->getAsCompiler()) - DeleteCompiler(base->getAsCompiler()); -} - -// -// Do an actual compile on the given strings. The result is left -// in the given compile object. -// -// Return: The return value of ShCompile is really boolean, indicating -// success or failure. -// -int ShCompile( - const ShHandle handle, - const char* const shaderStrings[], - size_t numStrings, - int compileOptions) -{ - if (handle == 0) - return 0; - - TShHandleBase* base = reinterpret_cast(handle); - TCompiler* compiler = base->getAsCompiler(); - if (compiler == 0) - return 0; - - bool success = compiler->compile(shaderStrings, numStrings, compileOptions); - return success ? 1 : 0; -} - -void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params) -{ - if (!handle || !params) - return; - - TShHandleBase* base = static_cast(handle); - TCompiler* compiler = base->getAsCompiler(); - if (!compiler) return; - - switch(pname) - { - case SH_INFO_LOG_LENGTH: - *params = compiler->getInfoSink().info.size() + 1; - break; - case SH_OBJECT_CODE_LENGTH: - *params = compiler->getInfoSink().obj.size() + 1; - break; - case SH_ACTIVE_UNIFORMS: - *params = compiler->getUniforms().size(); - break; - case SH_ACTIVE_UNIFORM_MAX_LENGTH: - *params = 1 + MAX_SYMBOL_NAME_LEN; - break; - case SH_ACTIVE_ATTRIBUTES: - *params = compiler->getAttribs().size(); - break; - case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: - *params = 1 + MAX_SYMBOL_NAME_LEN; - break; - case SH_VARYINGS: - *params = compiler->getVaryings().size(); - break; - case SH_VARYING_MAX_LENGTH: - *params = 1 + MAX_SYMBOL_NAME_LEN; - break; - case SH_MAPPED_NAME_MAX_LENGTH: - // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to - // handle array and struct dereferences. - *params = 1 + MAX_SYMBOL_NAME_LEN; - break; - case SH_NAME_MAX_LENGTH: - *params = 1 + MAX_SYMBOL_NAME_LEN; - break; - case SH_HASHED_NAME_MAX_LENGTH: - if (compiler->getHashFunction() == NULL) { - *params = 0; - } else { - // 64 bits hashing output requires 16 bytes for hex - // representation. - const char HashedNamePrefix[] = HASHED_NAME_PREFIX; - *params = 16 + sizeof(HashedNamePrefix); - } - break; - case SH_HASHED_NAMES_COUNT: - *params = compiler->getNameMap().size(); - break; - default: UNREACHABLE(); - } -} - -// -// Return any compiler log of messages for the application. -// -void ShGetInfoLog(const ShHandle handle, char* infoLog) -{ - if (!handle || !infoLog) - return; - - TShHandleBase* base = static_cast(handle); - TCompiler* compiler = base->getAsCompiler(); - if (!compiler) return; - - TInfoSink& infoSink = compiler->getInfoSink(); - strcpy(infoLog, infoSink.info.c_str()); -} - -// -// Return any object code. -// -void ShGetObjectCode(const ShHandle handle, char* objCode) -{ - if (!handle || !objCode) - return; - - TShHandleBase* base = static_cast(handle); - TCompiler* compiler = base->getAsCompiler(); - if (!compiler) return; - - TInfoSink& infoSink = compiler->getInfoSink(); - strcpy(objCode, infoSink.obj.c_str()); -} - -void ShGetVariableInfo(const ShHandle handle, - ShShaderInfo varType, - int index, - size_t* length, - int* size, - ShDataType* type, - ShPrecisionType* precision, - int* staticUse, - char* name, - char* mappedName) -{ - if (!handle || !size || !type || !precision || !staticUse || !name) - return; - ASSERT((varType == SH_ACTIVE_ATTRIBUTES) || - (varType == SH_ACTIVE_UNIFORMS) || - (varType == SH_VARYINGS)); - - TShHandleBase* base = reinterpret_cast(handle); - TCompiler* compiler = base->getAsCompiler(); - if (compiler == 0) - return; - - const TVariableInfoList& varList = - varType == SH_ACTIVE_ATTRIBUTES ? compiler->getAttribs() : - (varType == SH_ACTIVE_UNIFORMS ? compiler->getUniforms() : - compiler->getVaryings()); - 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; - switch (varInfo.precision) { - case EbpLow: - *precision = SH_PRECISION_LOWP; - break; - case EbpMedium: - *precision = SH_PRECISION_MEDIUMP; - break; - case EbpHigh: - *precision = SH_PRECISION_HIGHP; - break; - default: - // Some types does not support precision, for example, boolean. - *precision = SH_PRECISION_UNDEFINED; - break; - } - *staticUse = varInfo.staticUse ? 1 : 0; - - // This size must match that queried by - // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH - // in ShGetInfo, below. - size_t variableLength = 1 + MAX_SYMBOL_NAME_LEN; - ASSERT(checkVariableMaxLengths(handle, variableLength)); - strncpy(name, varInfo.name.c_str(), variableLength); - name[variableLength - 1] = 0; - if (mappedName) { - // This size must match that queried by - // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. - size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN; - ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength)); - strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength); - mappedName[maxMappedNameLength - 1] = 0; - } -} - -void ShGetNameHashingEntry(const ShHandle handle, - int index, - char* name, - char* hashedName) -{ - if (!handle || !name || !hashedName || index < 0) - return; - - TShHandleBase* base = static_cast(handle); - TCompiler* compiler = base->getAsCompiler(); - if (!compiler) return; - - const NameMap& nameMap = compiler->getNameMap(); - if (index >= static_cast(nameMap.size())) - return; - - NameMap::const_iterator it = nameMap.begin(); - for (int i = 0; i < index; ++i) - ++it; - - size_t len = it->first.length() + 1; - size_t max_len = 0; - ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len); - if (len > max_len) { - ASSERT(false); - len = max_len; - } - strncpy(name, it->first.c_str(), len); - // To be on the safe side in case the source is longer than expected. - name[len - 1] = '\0'; - - len = it->second.length() + 1; - max_len = 0; - ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len); - if (len > max_len) { - ASSERT(false); - len = max_len; - } - strncpy(hashedName, it->second.c_str(), len); - // To be on the safe side in case the source is longer than expected. - hashedName[len - 1] = '\0'; -} - -void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params) -{ - if (!handle || !params) - return; - - TShHandleBase* base = static_cast(handle); - TranslatorHLSL* translator = base->getAsTranslatorHLSL(); - if (!translator) return; - - switch(pname) - { - case SH_ACTIVE_UNIFORMS_ARRAY: - *params = (void*)&translator->getUniforms(); - break; - default: UNREACHABLE(); - } -} - -int ShCheckVariablesWithinPackingLimits( - int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize) -{ - if (varInfoArraySize == 0) - return 1; - ASSERT(varInfoArray); - TVariableInfoList variables; - for (size_t ii = 0; ii < varInfoArraySize; ++ii) - { - TVariableInfo var(varInfoArray[ii].type, varInfoArray[ii].size); - variables.push_back(var); - } - VariablePacker packer; - return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0; -} diff --git a/src/3rdparty/angle/src/compiler/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/SymbolTable.cpp deleted file mode 100644 index a7ce21680f..0000000000 --- a/src/3rdparty/angle/src/compiler/SymbolTable.cpp +++ /dev/null @@ -1,216 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// Symbol table for parsing. Most functionaliy and main ideas -// are documented in the header file. -// - -#if defined(_MSC_VER) -#pragma warning(disable: 4718) -#endif - -#include "compiler/SymbolTable.h" - -#include -#include -#include - -TType::TType(const TPublicType &p) : - type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), structure(0) -{ - if (p.userDef) - structure = p.userDef->getStruct(); -} - -// -// Recursively generate mangled names. -// -TString TType::buildMangledName() const -{ - TString mangledName; - if (isMatrix()) - mangledName += 'm'; - else if (isVector()) - mangledName += 'v'; - - switch (type) { - case EbtFloat: mangledName += 'f'; break; - case EbtInt: mangledName += 'i'; break; - case EbtBool: mangledName += 'b'; break; - case EbtSampler2D: mangledName += "s2"; break; - case EbtSamplerCube: mangledName += "sC"; break; - case EbtStruct: mangledName += structure->mangledName(); break; - default: break; - } - - mangledName += static_cast('0' + getNominalSize()); - if (isArray()) { - char buf[20]; - snprintf(buf, sizeof(buf), "%d", arraySize); - mangledName += '['; - mangledName += buf; - mangledName += ']'; - } - return mangledName; -} - -size_t TType::getObjectSize() const -{ - size_t totalSize = 0; - - if (getBasicType() == EbtStruct) - totalSize = structure->objectSize(); - else if (matrix) - totalSize = size * size; - else - totalSize = size; - - if (isArray()) { - size_t arraySize = getArraySize(); - if (arraySize > INT_MAX / totalSize) - totalSize = INT_MAX; - else - totalSize *= arraySize; - } - - return totalSize; -} - -bool TStructure::containsArrays() const -{ - for (size_t i = 0; i < mFields->size(); ++i) { - const TType* fieldType = (*mFields)[i]->type(); - if (fieldType->isArray() || fieldType->isStructureContainingArrays()) - return true; - } - return false; -} - -TString TStructure::buildMangledName() const -{ - TString mangledName("struct-"); - mangledName += *mName; - for (size_t i = 0; i < mFields->size(); ++i) { - mangledName += '-'; - mangledName += (*mFields)[i]->type()->getMangledName(); - } - return mangledName; -} - -size_t TStructure::calculateObjectSize() const -{ - size_t size = 0; - for (size_t i = 0; i < mFields->size(); ++i) { - size_t fieldSize = (*mFields)[i]->type()->getObjectSize(); - if (fieldSize > INT_MAX - size) - size = INT_MAX; - else - size += fieldSize; - } - return size; -} - -int TStructure::calculateDeepestNesting() const -{ - int maxNesting = 0; - for (size_t i = 0; i < mFields->size(); ++i) { - maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting()); - } - return 1 + maxNesting; -} - -// -// Dump functions. -// - -void TVariable::dump(TInfoSink& infoSink) const -{ - infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getPrecisionString() << " " << type.getBasicString(); - if (type.isArray()) { - infoSink.debug << "[0]"; - } - infoSink.debug << "\n"; -} - -void TFunction::dump(TInfoSink &infoSink) const -{ - infoSink.debug << getName().c_str() << ": " << returnType.getBasicString() << " " << getMangledName().c_str() << "\n"; -} - -void TSymbolTableLevel::dump(TInfoSink &infoSink) const -{ - tLevel::const_iterator it; - for (it = level.begin(); it != level.end(); ++it) - (*it).second->dump(infoSink); -} - -void TSymbolTable::dump(TInfoSink &infoSink) const -{ - for (int level = currentLevel(); level >= 0; --level) { - infoSink.debug << "LEVEL " << level << "\n"; - table[level]->dump(infoSink); - } -} - -// -// Functions have buried pointers to delete. -// -TFunction::~TFunction() -{ - for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i) - delete (*i).type; -} - -// -// Symbol table levels are a map of pointers to symbols that have to be deleted. -// -TSymbolTableLevel::~TSymbolTableLevel() -{ - for (tLevel::iterator it = level.begin(); it != level.end(); ++it) - delete (*it).second; -} - -// -// Change all function entries in the table with the non-mangled name -// to be related to the provided built-in operation. This is a low -// performance operation, and only intended for symbol tables that -// live across a large number of compiles. -// -void TSymbolTableLevel::relateToOperator(const char* name, TOperator op) -{ - tLevel::iterator it; - for (it = level.begin(); it != level.end(); ++it) { - if ((*it).second->isFunction()) { - TFunction* function = static_cast((*it).second); - if (function->getName() == name) - function->relateToOperator(op); - } - } -} - -// -// Change all function entries in the table with the non-mangled name -// to be related to the provided built-in extension. This is a low -// performance operation, and only intended for symbol tables that -// live across a large number of compiles. -// -void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext) -{ - for (tLevel::iterator it = level.begin(); it != level.end(); ++it) { - TSymbol* symbol = it->second; - if (symbol->getName() == name) - symbol->relateToExtension(ext); - } -} - -TSymbolTable::~TSymbolTable() -{ - for (size_t i = 0; i < table.size(); ++i) - delete table[i]; - for (size_t i = 0; i < precisionStack.size(); ++i) - delete precisionStack[i]; -} diff --git a/src/3rdparty/angle/src/compiler/SymbolTable.h b/src/3rdparty/angle/src/compiler/SymbolTable.h deleted file mode 100644 index bebad4b92e..0000000000 --- a/src/3rdparty/angle/src/compiler/SymbolTable.h +++ /dev/null @@ -1,382 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef _SYMBOL_TABLE_INCLUDED_ -#define _SYMBOL_TABLE_INCLUDED_ - -// -// Symbol table for parsing. Has these design characteristics: -// -// * Same symbol table can be used to compile many shaders, to preserve -// effort of creating and loading with the large numbers of built-in -// symbols. -// -// * Name mangling will be used to give each function a unique name -// so that symbol table lookups are never ambiguous. This allows -// a simpler symbol table structure. -// -// * Pushing and popping of scope, so symbol table will really be a stack -// of symbol tables. Searched from the top, with new inserts going into -// the top. -// -// * Constants: Compile time constant symbols will keep their values -// in the symbol table. The parser can substitute constants at parse -// time, including doing constant folding and constant propagation. -// -// * No temporaries: Temporaries made from operations (+, --, .xy, etc.) -// are tracked in the intermediate representation, not the symbol table. -// - -#include - -#include "common/angleutils.h" -#include "compiler/InfoSink.h" -#include "compiler/intermediate.h" - -// -// Symbol base class. (Can build functions or variables out of these...) -// -class TSymbol { -public: - POOL_ALLOCATOR_NEW_DELETE(); - TSymbol(const TString* n) : uniqueId(0), name(n) { } - virtual ~TSymbol() { /* don't delete name, it's from the pool */ } - - const TString& getName() const { return *name; } - virtual const TString& getMangledName() const { return getName(); } - virtual bool isFunction() const { return false; } - virtual bool isVariable() const { return false; } - void setUniqueId(int id) { uniqueId = id; } - int getUniqueId() const { return uniqueId; } - virtual void dump(TInfoSink &infoSink) const = 0; - void relateToExtension(const TString& ext) { extension = ext; } - const TString& getExtension() const { return extension; } - -private: - DISALLOW_COPY_AND_ASSIGN(TSymbol); - - int uniqueId; // For real comparing during code generation - const TString *name; - TString extension; -}; - -// -// Variable class, meaning a symbol that's not a function. -// -// There could be a separate class heirarchy for Constant variables; -// Only one of int, bool, or float, (or none) is correct for -// any particular use, but it's easy to do this way, and doesn't -// seem worth having separate classes, and "getConst" can't simply return -// different values for different types polymorphically, so this is -// just simple and pragmatic. -// -class TVariable : public TSymbol { -public: - TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0) { } - virtual ~TVariable() { } - virtual bool isVariable() const { return true; } - TType& getType() { return type; } - const TType& getType() const { return type; } - bool isUserType() const { return userType; } - void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); } - - virtual void dump(TInfoSink &infoSink) const; - - ConstantUnion* getConstPointer() - { - if (!unionArray) - unionArray = new ConstantUnion[type.getObjectSize()]; - - return unionArray; - } - - ConstantUnion* getConstPointer() const { return unionArray; } - - void shareConstPointer( ConstantUnion *constArray) - { - if (unionArray == constArray) - return; - - delete[] unionArray; - unionArray = constArray; - } - -private: - DISALLOW_COPY_AND_ASSIGN(TVariable); - - TType type; - bool userType; - // we are assuming that Pool Allocator will free the memory allocated to unionArray - // when this object is destroyed - ConstantUnion *unionArray; -}; - -// -// The function sub-class of symbols and the parser will need to -// share this definition of a function parameter. -// -struct TParameter { - TString *name; - TType* type; -}; - -// -// The function sub-class of a symbol. -// -class TFunction : public TSymbol { -public: - TFunction(TOperator o) : - TSymbol(0), - returnType(TType(EbtVoid, EbpUndefined)), - op(o), - defined(false) { } - TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) : - TSymbol(name), - returnType(retType), - mangledName(TFunction::mangleName(*name)), - op(tOp), - defined(false) { } - virtual ~TFunction(); - virtual bool isFunction() const { return true; } - - static TString mangleName(const TString& name) { return name + '('; } - static TString unmangleName(const TString& mangledName) - { - return TString(mangledName.c_str(), mangledName.find_first_of('(')); - } - - void addParameter(TParameter& p) - { - parameters.push_back(p); - mangledName = mangledName + p.type->getMangledName(); - } - - const TString& getMangledName() const { return mangledName; } - const TType& getReturnType() const { return returnType; } - - void relateToOperator(TOperator o) { op = o; } - TOperator getBuiltInOp() const { return op; } - - void setDefined() { defined = true; } - bool isDefined() { return defined; } - - size_t getParamCount() const { return parameters.size(); } - const TParameter& getParam(size_t i) const { return parameters[i]; } - - virtual void dump(TInfoSink &infoSink) const; - -private: - DISALLOW_COPY_AND_ASSIGN(TFunction); - - typedef TVector TParamList; - TParamList parameters; - TType returnType; - TString mangledName; - TOperator op; - bool defined; -}; - - -class TSymbolTableLevel { -public: - typedef TMap tLevel; - typedef tLevel::const_iterator const_iterator; - typedef const tLevel::value_type tLevelPair; - typedef std::pair tInsertResult; - - TSymbolTableLevel() { } - ~TSymbolTableLevel(); - - bool insert(const TString &name, TSymbol &symbol) - { - // - // returning true means symbol was added to the table - // - tInsertResult result = level.insert(tLevelPair(name, &symbol)); - - return result.second; - } - - bool insert(TSymbol &symbol) - { - return insert(symbol.getMangledName(), symbol); - } - - TSymbol* find(const TString& name) const - { - tLevel::const_iterator it = level.find(name); - if (it == level.end()) - return 0; - else - return (*it).second; - } - - const_iterator begin() const - { - return level.begin(); - } - - const_iterator end() const - { - return level.end(); - } - - void relateToOperator(const char* name, TOperator op); - void relateToExtension(const char* name, const TString& ext); - void dump(TInfoSink &infoSink) const; - -protected: - tLevel level; -}; - -class TSymbolTable { -public: - TSymbolTable() : uniqueId(0) - { - // - // The symbol table cannot be used until push() is called, but - // the lack of an initial call to push() can be used to detect - // that the symbol table has not been preloaded with built-ins. - // - } - ~TSymbolTable(); - - // - // When the symbol table is initialized with the built-ins, there should - // 'push' calls, so that built-ins are at level 0 and the shader - // globals are at level 1. - // - bool isEmpty() { return table.size() == 0; } - bool atBuiltInLevel() { return table.size() == 1; } - bool atGlobalLevel() { return table.size() <= 2; } - void push() - { - table.push_back(new TSymbolTableLevel); - precisionStack.push_back(new PrecisionStackLevel); - } - - void pop() - { - delete table.back(); - table.pop_back(); - - delete precisionStack.back(); - precisionStack.pop_back(); - } - - bool insert(TSymbol& symbol) - { - symbol.setUniqueId(++uniqueId); - return table[currentLevel()]->insert(symbol); - } - - bool insertConstInt(const char *name, int value) - { - TVariable *constant = new TVariable(NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1)); - constant->getConstPointer()->setIConst(value); - return insert(*constant); - } - - bool insertBuiltIn(TType *rvalue, const char *name, TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0) - { - TFunction *function = new TFunction(NewPoolTString(name), *rvalue); - - TParameter param1 = {NULL, ptype1}; - function->addParameter(param1); - - if(ptype2) - { - TParameter param2 = {NULL, ptype2}; - function->addParameter(param2); - } - - if(ptype3) - { - TParameter param3 = {NULL, ptype3}; - function->addParameter(param3); - } - - return insert(*function); - } - - TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0) - { - int level = currentLevel(); - TSymbol* symbol; - do { - symbol = table[level]->find(name); - --level; - } while (symbol == 0 && level >= 0); - level++; - if (builtIn) - *builtIn = level == 0; - if (sameScope) - *sameScope = level == currentLevel(); - return symbol; - } - - TSymbol* findBuiltIn(const TString &name) - { - return table[0]->find(name); - } - - TSymbolTableLevel* getOuterLevel() { - assert(table.size() >= 2); - return table[currentLevel() - 1]; - } - - void relateToOperator(const char* name, TOperator op) { - table[0]->relateToOperator(name, op); - } - void relateToExtension(const char* name, const TString& ext) { - table[0]->relateToExtension(name, ext); - } - void dump(TInfoSink &infoSink) const; - - bool setDefaultPrecision(const TPublicType& type, TPrecision prec) { - if (!supportsPrecision(type.type)) - return false; - if (type.size != 1 || type.matrix || type.array) - return false; // Not allowed to set for aggregate types - int indexOfLastElement = static_cast(precisionStack.size()) - 1; - (*precisionStack[indexOfLastElement])[type.type] = prec; // Uses map operator [], overwrites the current value - return true; - } - - // Searches down the precisionStack for a precision qualifier for the specified TBasicType - TPrecision getDefaultPrecision(TBasicType type) { - if (!supportsPrecision(type)) - return EbpUndefined; - int level = static_cast(precisionStack.size()) - 1; - assert(level >= 0); // Just to be safe. Should not happen. - PrecisionStackLevel::iterator it; - TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this? - while (level >= 0) { - it = precisionStack[level]->find(type); - if (it != precisionStack[level]->end()) { - prec = (*it).second; - break; - } - level--; - } - return prec; - } - -private: - int currentLevel() const { return static_cast(table.size()) - 1; } - - bool supportsPrecision(TBasicType type) { - // Only supports precision for int, float, and sampler types. - return type == EbtFloat || type == EbtInt || IsSampler(type); - } - - int uniqueId; // for unique identification in code generation - std::vector table; - typedef TMap PrecisionStackLevel; - std::vector precisionStack; -}; - -#endif // _SYMBOL_TABLE_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/TranslatorESSL.cpp b/src/3rdparty/angle/src/compiler/TranslatorESSL.cpp deleted file mode 100644 index 2900f8a8ed..0000000000 --- a/src/3rdparty/angle/src/compiler/TranslatorESSL.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/TranslatorESSL.h" - -#include "compiler/OutputESSL.h" - -TranslatorESSL::TranslatorESSL(ShShaderType type, ShShaderSpec spec) - : TCompiler(type, spec) { -} - -void TranslatorESSL::translate(TIntermNode* root) { - TInfoSinkBase& sink = getInfoSink().obj; - - // Write built-in extension behaviors. - writeExtensionBehavior(); - - // Write emulated built-in functions if needed. - getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition( - sink, getShaderType() == SH_FRAGMENT_SHADER); - - // Write array bounds clamping emulation if needed. - getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); - - // Write translated shader. - TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable()); - root->traverse(&outputESSL); -} - -void TranslatorESSL::writeExtensionBehavior() { - TInfoSinkBase& sink = getInfoSink().obj; - const TExtensionBehavior& extensionBehavior = getExtensionBehavior(); - for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin(); - iter != extensionBehavior.end(); ++iter) { - if (iter->second != EBhUndefined) { - sink << "#extension " << iter->first << " : " - << getBehaviorString(iter->second) << "\n"; - } - } -} diff --git a/src/3rdparty/angle/src/compiler/TranslatorESSL.h b/src/3rdparty/angle/src/compiler/TranslatorESSL.h deleted file mode 100644 index a1196bd001..0000000000 --- a/src/3rdparty/angle/src/compiler/TranslatorESSL.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATORESSL_H_ -#define COMPILER_TRANSLATORESSL_H_ - -#include "compiler/ShHandle.h" - -class TranslatorESSL : public TCompiler { -public: - TranslatorESSL(ShShaderType type, ShShaderSpec spec); - -protected: - virtual void translate(TIntermNode* root); - -private: - void writeExtensionBehavior(); -}; - -#endif // COMPILER_TRANSLATORESSL_H_ diff --git a/src/3rdparty/angle/src/compiler/TranslatorGLSL.cpp b/src/3rdparty/angle/src/compiler/TranslatorGLSL.cpp deleted file mode 100644 index 7ca4341dcd..0000000000 --- a/src/3rdparty/angle/src/compiler/TranslatorGLSL.cpp +++ /dev/null @@ -1,44 +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. -// - -#include "compiler/TranslatorGLSL.h" - -#include "compiler/OutputGLSL.h" -#include "compiler/VersionGLSL.h" - -static void writeVersion(ShShaderType type, TIntermNode* root, - TInfoSinkBase& sink) { - TVersionGLSL versionGLSL(type); - root->traverse(&versionGLSL); - int version = versionGLSL.getVersion(); - // We need to write version directive only if it is greater than 110. - // If there is no version directive in the shader, 110 is implied. - if (version > 110) { - sink << "#version " << version << "\n"; - } -} - -TranslatorGLSL::TranslatorGLSL(ShShaderType type, ShShaderSpec spec) - : TCompiler(type, spec) { -} - -void TranslatorGLSL::translate(TIntermNode* root) { - TInfoSinkBase& sink = getInfoSink().obj; - - // Write GLSL version. - writeVersion(getShaderType(), root, sink); - - // Write emulated built-in functions if needed. - getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition( - sink, false); - - // Write array bounds clamping emulation if needed. - getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); - - // Write translated shader. - TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable()); - root->traverse(&outputGLSL); -} diff --git a/src/3rdparty/angle/src/compiler/TranslatorGLSL.h b/src/3rdparty/angle/src/compiler/TranslatorGLSL.h deleted file mode 100644 index c2ce06d192..0000000000 --- a/src/3rdparty/angle/src/compiler/TranslatorGLSL.h +++ /dev/null @@ -1,20 +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. -// - -#ifndef COMPILER_TRANSLATORGLSL_H_ -#define COMPILER_TRANSLATORGLSL_H_ - -#include "compiler/ShHandle.h" - -class TranslatorGLSL : public TCompiler { -public: - TranslatorGLSL(ShShaderType type, ShShaderSpec spec); - -protected: - virtual void translate(TIntermNode* root); -}; - -#endif // COMPILER_TRANSLATORGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/TranslatorHLSL.cpp b/src/3rdparty/angle/src/compiler/TranslatorHLSL.cpp deleted file mode 100644 index 37408a07c4..0000000000 --- a/src/3rdparty/angle/src/compiler/TranslatorHLSL.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/TranslatorHLSL.h" - -#include "compiler/InitializeParseContext.h" -#include "compiler/OutputHLSL.h" - -TranslatorHLSL::TranslatorHLSL(ShShaderType type, ShShaderSpec spec, ShShaderOutput output) - : TCompiler(type, spec), mOutputType(output) -{ -} - -void TranslatorHLSL::translate(TIntermNode *root) -{ - TParseContext& parseContext = *GetGlobalParseContext(); - sh::OutputHLSL outputHLSL(parseContext, getResources(), mOutputType); - - outputHLSL.output(); - mActiveUniforms = outputHLSL.getUniforms(); -} diff --git a/src/3rdparty/angle/src/compiler/TranslatorHLSL.h b/src/3rdparty/angle/src/compiler/TranslatorHLSL.h deleted file mode 100644 index 9550e15e8e..0000000000 --- a/src/3rdparty/angle/src/compiler/TranslatorHLSL.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATORHLSL_H_ -#define COMPILER_TRANSLATORHLSL_H_ - -#include "compiler/ShHandle.h" -#include "compiler/Uniform.h" - -class TranslatorHLSL : public TCompiler { -public: - TranslatorHLSL(ShShaderType type, ShShaderSpec spec, ShShaderOutput output); - - virtual TranslatorHLSL *getAsTranslatorHLSL() { return this; } - const sh::ActiveUniforms &getUniforms() { return mActiveUniforms; } - -protected: - virtual void translate(TIntermNode* root); - - sh::ActiveUniforms mActiveUniforms; - ShShaderOutput mOutputType; -}; - -#endif // COMPILER_TRANSLATORHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/Types.h b/src/3rdparty/angle/src/compiler/Types.h deleted file mode 100644 index 505fa8e3bf..0000000000 --- a/src/3rdparty/angle/src/compiler/Types.h +++ /dev/null @@ -1,307 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef _TYPES_INCLUDED -#define _TYPES_INCLUDED - -#include "common/angleutils.h" - -#include "compiler/BaseTypes.h" -#include "compiler/Common.h" -#include "compiler/debug.h" - -struct TPublicType; -class TType; - -class TField -{ -public: - POOL_ALLOCATOR_NEW_DELETE(); - TField(TType* type, TString* name) : mType(type), mName(name) {} - - // TODO(alokp): We should only return const type. - // Fix it by tweaking grammar. - TType* type() { return mType; } - const TType* type() const { return mType; } - - const TString& name() const { return *mName; } - -private: - DISALLOW_COPY_AND_ASSIGN(TField); - TType* mType; - TString* mName; -}; - -typedef TVector TFieldList; -inline TFieldList* NewPoolTFieldList() -{ - void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList)); - return new(memory) TFieldList; -} - -class TStructure -{ -public: - POOL_ALLOCATOR_NEW_DELETE(); - TStructure(TString* name, TFieldList* fields) - : mName(name), - mFields(fields), - mObjectSize(0), - mDeepestNesting(0) { - } - - const TString& name() const { return *mName; } - const TFieldList& fields() const { return *mFields; } - - const TString& mangledName() const { - if (mMangledName.empty()) - mMangledName = buildMangledName(); - return mMangledName; - } - size_t objectSize() const { - if (mObjectSize == 0) - mObjectSize = calculateObjectSize(); - return mObjectSize; - }; - int deepestNesting() const { - if (mDeepestNesting == 0) - mDeepestNesting = calculateDeepestNesting(); - return mDeepestNesting; - } - bool containsArrays() const; - -private: - DISALLOW_COPY_AND_ASSIGN(TStructure); - TString buildMangledName() const; - size_t calculateObjectSize() const; - int calculateDeepestNesting() const; - - TString* mName; - TFieldList* mFields; - - mutable TString mMangledName; - mutable size_t mObjectSize; - mutable int mDeepestNesting; -}; - -// -// Base class for things that have a type. -// -class TType -{ -public: - POOL_ALLOCATOR_NEW_DELETE(); - 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) - { - } - explicit TType(const TPublicType &p); - TType(TStructure* userDef, TPrecision p = EbpUndefined) : - type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), structure(userDef) - { - } - - TBasicType getBasicType() const { return type; } - void setBasicType(TBasicType t) { type = t; } - - TPrecision getPrecision() const { return precision; } - void setPrecision(TPrecision p) { precision = p; } - - TQualifier getQualifier() const { return qualifier; } - void setQualifier(TQualifier q) { qualifier = q; } - - // One-dimensional size of single instance type - int getNominalSize() const { return size; } - void setNominalSize(int s) { size = s; } - // Full size of single instance of type - size_t getObjectSize() const; - - int elementRegisterCount() const - { - if (structure) - { - const TFieldList &fields = getStruct()->fields(); - int registerCount = 0; - - for (size_t i = 0; i < fields.size(); i++) - { - registerCount += fields[i]->type()->totalRegisterCount(); - } - - return registerCount; - } - else if (isMatrix()) - { - return getNominalSize(); - } - else - { - return 1; - } - } - - int totalRegisterCount() const - { - if (array) - { - return arraySize * elementRegisterCount(); - } - else - { - return elementRegisterCount(); - } - } - - bool isMatrix() const { return matrix ? true : false; } - void setMatrix(bool m) { matrix = m; } - - bool isArray() const { return array ? true : false; } - int getArraySize() const { return arraySize; } - void setArraySize(int s) { array = true; arraySize = s; } - void clearArrayness() { array = false; arraySize = 0; } - - bool isVector() const { return size > 1 && !matrix; } - bool isScalar() const { return size == 1 && !matrix && !structure; } - - TStructure* getStruct() const { return structure; } - void setStruct(TStructure* s) { structure = s; } - - const TString& getMangledName() const { - if (mangled.empty()) { - mangled = buildMangledName(); - mangled += ';'; - } - return mangled; - } - - bool sameElementType(const TType& right) const { - return type == right.type && - size == right.size && - matrix == right.matrix && - structure == right.structure; - } - bool operator==(const TType& right) const { - return type == right.type && - size == right.size && - matrix == right.matrix && - array == right.array && (!array || arraySize == right.arraySize) && - structure == right.structure; - // don't check the qualifier, it's not ever what's being sought after - } - bool operator!=(const TType& right) const { - return !operator==(right); - } - bool operator<(const TType& right) const { - if (type != right.type) return type < right.type; - if (size != right.size) return size < right.size; - if (matrix != right.matrix) return matrix < right.matrix; - if (array != right.array) return array < right.array; - if (arraySize != right.arraySize) return arraySize < right.arraySize; - if (structure != right.structure) return structure < right.structure; - - return false; - } - - const char* getBasicString() const { return ::getBasicString(type); } - const char* getPrecisionString() const { return ::getPrecisionString(precision); } - const char* getQualifierString() const { return ::getQualifierString(qualifier); } - TString getCompleteString() const; - - // If this type is a struct, returns the deepest struct nesting of - // any field in the struct. For example: - // struct nesting1 { - // vec4 position; - // }; - // struct nesting2 { - // nesting1 field1; - // vec4 field2; - // }; - // For type "nesting2", this method would return 2 -- the number - // of structures through which indirection must occur to reach the - // deepest field (nesting2.field1.position). - int getDeepestStructNesting() const { - return structure ? structure->deepestNesting() : 0; - } - - bool isStructureContainingArrays() const { - return structure ? structure->containsArrays() : false; - } - -private: - TString buildMangledName() const; - - TBasicType type : 6; - TPrecision precision; - TQualifier qualifier : 7; - int size : 8; // size of vector or matrix, not size of array - unsigned int matrix : 1; - unsigned int array : 1; - int arraySize; - - TStructure* structure; // 0 unless this is a struct - - mutable TString mangled; -}; - -// -// This is a workaround for a problem with the yacc stack, It can't have -// types that it thinks have non-trivial constructors. It should -// just be used while recognizing the grammar, not anything else. Pointers -// could be used, but also trying to avoid lots of memory management overhead. -// -// Not as bad as it looks, there is no actual assumption that the fields -// match up or are name the same or anything like that. -// -struct TPublicType -{ - TBasicType type; - TQualifier qualifier; - TPrecision precision; - int size; // size of vector or matrix, not size of array - bool matrix; - bool array; - int arraySize; - TType* userDef; - TSourceLoc line; - - void setBasic(TBasicType bt, TQualifier q, const TSourceLoc& ln) - { - type = bt; - qualifier = q; - precision = EbpUndefined; - size = 1; - matrix = false; - array = false; - arraySize = 0; - userDef = 0; - line = ln; - } - - void setAggregate(int s, bool m = false) - { - size = s; - matrix = m; - } - - void setArray(bool a, int s = 0) - { - array = a; - arraySize = s; - } - - bool isStructureContainingArrays() const - { - if (!userDef) - { - return false; - } - - return userDef->isStructureContainingArrays(); - } -}; - -#endif // _TYPES_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp b/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp deleted file mode 100644 index 47f0afca6a..0000000000 --- a/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp +++ /dev/null @@ -1,176 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements. -// The results are assigned to s# temporaries, which are used by the main translator instead of -// the original expression. -// - -#include "compiler/UnfoldShortCircuit.h" - -#include "compiler/InfoSink.h" -#include "compiler/OutputHLSL.h" - -namespace sh -{ -UnfoldShortCircuit::UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL) : mContext(context), mOutputHLSL(outputHLSL) -{ - mTemporaryIndex = 0; -} - -void UnfoldShortCircuit::traverse(TIntermNode *node) -{ - int rewindIndex = mTemporaryIndex; - node->traverse(this); - mTemporaryIndex = rewindIndex; -} - -bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node) -{ - TInfoSinkBase &out = mOutputHLSL->getBodyStream(); - - switch (node->getOp()) - { - case EOpLogicalOr: - // "x || y" is equivalent to "x ? true : y", which unfolds to "bool s; if(x) s = true; else s = y;", - // and then further simplifies down to "bool s = x; if(!s) s = y;". - { - int i = mTemporaryIndex; - - out << "bool s" << i << ";\n"; - - out << "{\n"; - - mTemporaryIndex = i + 1; - node->getLeft()->traverse(this); - out << "s" << i << " = "; - mTemporaryIndex = i + 1; - node->getLeft()->traverse(mOutputHLSL); - out << ";\n"; - out << "if(!s" << i << ")\n" - "{\n"; - mTemporaryIndex = i + 1; - node->getRight()->traverse(this); - out << " s" << i << " = "; - mTemporaryIndex = i + 1; - node->getRight()->traverse(mOutputHLSL); - out << ";\n" - "}\n"; - - out << "}\n"; - - mTemporaryIndex = i + 1; - } - return false; - case EOpLogicalAnd: - // "x && y" is equivalent to "x ? y : false", which unfolds to "bool s; if(x) s = y; else s = false;", - // and then further simplifies down to "bool s = x; if(s) s = y;". - { - int i = mTemporaryIndex; - - out << "bool s" << i << ";\n"; - - out << "{\n"; - - mTemporaryIndex = i + 1; - node->getLeft()->traverse(this); - out << "s" << i << " = "; - mTemporaryIndex = i + 1; - node->getLeft()->traverse(mOutputHLSL); - out << ";\n"; - out << "if(s" << i << ")\n" - "{\n"; - mTemporaryIndex = i + 1; - node->getRight()->traverse(this); - out << " s" << i << " = "; - mTemporaryIndex = i + 1; - node->getRight()->traverse(mOutputHLSL); - out << ";\n" - "}\n"; - - out << "}\n"; - - mTemporaryIndex = i + 1; - } - return false; - default: - return true; - } -} - -bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node) -{ - TInfoSinkBase &out = mOutputHLSL->getBodyStream(); - - // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;" - if (node->usesTernaryOperator()) - { - int i = mTemporaryIndex; - - out << mOutputHLSL->typeString(node->getType()) << " s" << i << ";\n"; - - out << "{\n"; - - mTemporaryIndex = i + 1; - node->getCondition()->traverse(this); - out << "if("; - mTemporaryIndex = i + 1; - node->getCondition()->traverse(mOutputHLSL); - out << ")\n" - "{\n"; - mTemporaryIndex = i + 1; - node->getTrueBlock()->traverse(this); - out << " s" << i << " = "; - mTemporaryIndex = i + 1; - node->getTrueBlock()->traverse(mOutputHLSL); - out << ";\n" - "}\n" - "else\n" - "{\n"; - mTemporaryIndex = i + 1; - node->getFalseBlock()->traverse(this); - out << " s" << i << " = "; - mTemporaryIndex = i + 1; - node->getFalseBlock()->traverse(mOutputHLSL); - out << ";\n" - "}\n"; - - out << "}\n"; - - mTemporaryIndex = i + 1; - } - - return false; -} - -bool UnfoldShortCircuit::visitLoop(Visit visit, TIntermLoop *node) -{ - int rewindIndex = mTemporaryIndex; - - if (node->getInit()) - { - node->getInit()->traverse(this); - } - - if (node->getCondition()) - { - node->getCondition()->traverse(this); - } - - if (node->getExpression()) - { - node->getExpression()->traverse(this); - } - - mTemporaryIndex = rewindIndex; - - return false; -} - -int UnfoldShortCircuit::getNextTemporaryIndex() -{ - return mTemporaryIndex++; -} -} diff --git a/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.h b/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.h deleted file mode 100644 index cb176a5f1c..0000000000 --- a/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements -// - -#ifndef COMPILER_UNFOLDSHORTCIRCUIT_H_ -#define COMPILER_UNFOLDSHORTCIRCUIT_H_ - -#include "compiler/intermediate.h" -#include "compiler/ParseHelper.h" - -namespace sh -{ -class OutputHLSL; - -class UnfoldShortCircuit : public TIntermTraverser -{ - public: - UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL); - - void traverse(TIntermNode *node); - bool visitBinary(Visit visit, TIntermBinary*); - bool visitSelection(Visit visit, TIntermSelection *node); - bool visitLoop(Visit visit, TIntermLoop *node); - - int getNextTemporaryIndex(); - - protected: - TParseContext &mContext; - OutputHLSL *const mOutputHLSL; - - int mTemporaryIndex; -}; -} - -#endif // COMPILER_UNFOLDSHORTCIRCUIT_H_ diff --git a/src/3rdparty/angle/src/compiler/Uniform.cpp b/src/3rdparty/angle/src/compiler/Uniform.cpp deleted file mode 100644 index f367db2be8..0000000000 --- a/src/3rdparty/angle/src/compiler/Uniform.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/Uniform.h" - -namespace sh -{ - -Uniform::Uniform(GLenum type, GLenum precision, const char *name, int arraySize, int registerIndex) -{ - this->type = type; - this->precision = precision; - this->name = name; - this->arraySize = arraySize; - this->registerIndex = registerIndex; -} - -} diff --git a/src/3rdparty/angle/src/compiler/Uniform.h b/src/3rdparty/angle/src/compiler/Uniform.h deleted file mode 100644 index 4c53ffa7d2..0000000000 --- a/src/3rdparty/angle/src/compiler/Uniform.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_UNIFORM_H_ -#define COMPILER_UNIFORM_H_ - -#include -#include - -#define GL_APICALL -#include - -namespace sh -{ - -struct Uniform -{ - Uniform(GLenum type, GLenum precision, const char *name, int arraySize, int registerIndex); - - GLenum type; - GLenum precision; - std::string name; - unsigned int arraySize; - - int registerIndex; -}; - -typedef std::vector ActiveUniforms; - -} - -#endif // COMPILER_UNIFORM_H_ diff --git a/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp deleted file mode 100644 index 736ceeaefc..0000000000 --- a/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp +++ /dev/null @@ -1,512 +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. -// - -#include "compiler/ValidateLimitations.h" -#include "compiler/InfoSink.h" -#include "compiler/InitializeParseContext.h" -#include "compiler/ParseHelper.h" - -namespace { -bool IsLoopIndex(const TIntermSymbol* symbol, const TLoopStack& stack) { - for (TLoopStack::const_iterator i = stack.begin(); i != stack.end(); ++i) { - if (i->index.id == symbol->getId()) - return true; - } - return false; -} - -void MarkLoopForUnroll(const TIntermSymbol* symbol, TLoopStack& stack) { - for (TLoopStack::iterator i = stack.begin(); i != stack.end(); ++i) { - if (i->index.id == symbol->getId()) { - ASSERT(i->loop != NULL); - i->loop->setUnrollFlag(true); - return; - } - } - UNREACHABLE(); -} - -// Traverses a node to check if it represents a constant index expression. -// Definition: -// constant-index-expressions are a superset of constant-expressions. -// Constant-index-expressions can include loop indices as defined in -// GLSL ES 1.0 spec, Appendix A, section 4. -// The following are constant-index-expressions: -// - Constant expressions -// - Loop indices as defined in section 4 -// - Expressions composed of both of the above -class ValidateConstIndexExpr : public TIntermTraverser { -public: - ValidateConstIndexExpr(const TLoopStack& stack) - : mValid(true), mLoopStack(stack) {} - - // Returns true if the parsed node represents a constant index expression. - bool isValid() const { return mValid; } - - virtual void visitSymbol(TIntermSymbol* symbol) { - // Only constants and loop indices are allowed in a - // constant index expression. - if (mValid) { - mValid = (symbol->getQualifier() == EvqConst) || - IsLoopIndex(symbol, mLoopStack); - } - } - -private: - bool mValid; - const TLoopStack& mLoopStack; -}; - -// Traverses a node to check if it uses a loop index. -// If an int loop index is used in its body as a sampler array index, -// mark the loop for unroll. -class ValidateLoopIndexExpr : public TIntermTraverser { -public: - ValidateLoopIndexExpr(TLoopStack& stack) - : mUsesFloatLoopIndex(false), - mUsesIntLoopIndex(false), - mLoopStack(stack) {} - - bool usesFloatLoopIndex() const { return mUsesFloatLoopIndex; } - bool usesIntLoopIndex() const { return mUsesIntLoopIndex; } - - virtual void visitSymbol(TIntermSymbol* symbol) { - if (IsLoopIndex(symbol, mLoopStack)) { - switch (symbol->getBasicType()) { - case EbtFloat: - mUsesFloatLoopIndex = true; - break; - case EbtInt: - mUsesIntLoopIndex = true; - MarkLoopForUnroll(symbol, mLoopStack); - break; - default: - UNREACHABLE(); - } - } - } - -private: - bool mUsesFloatLoopIndex; - bool mUsesIntLoopIndex; - TLoopStack& mLoopStack; -}; -} // namespace - -ValidateLimitations::ValidateLimitations(ShShaderType shaderType, - TInfoSinkBase& sink) - : mShaderType(shaderType), - mSink(sink), - mNumErrors(0) -{ -} - -bool ValidateLimitations::visitBinary(Visit, TIntermBinary* node) -{ - // Check if loop index is modified in the loop body. - validateOperation(node, node->getLeft()); - - // Check indexing. - switch (node->getOp()) { - case EOpIndexDirect: - validateIndexing(node); - break; - case EOpIndexIndirect: -#if defined(__APPLE__) - // Loop unrolling is a work-around for a Mac Cg compiler bug where it - // crashes when a sampler array's index is also the loop index. - // Once Apple fixes this bug, we should remove the code in this CL. - // See http://codereview.appspot.com/4331048/. - if ((node->getLeft() != NULL) && (node->getRight() != NULL) && - (node->getLeft()->getAsSymbolNode())) { - TIntermSymbol* symbol = node->getLeft()->getAsSymbolNode(); - if (IsSampler(symbol->getBasicType()) && symbol->isArray()) { - ValidateLoopIndexExpr validate(mLoopStack); - node->getRight()->traverse(&validate); - if (validate.usesFloatLoopIndex()) { - error(node->getLine(), - "sampler array index is float loop index", - "for"); - } - } - } -#endif - validateIndexing(node); - break; - default: break; - } - return true; -} - -bool ValidateLimitations::visitUnary(Visit, TIntermUnary* node) -{ - // Check if loop index is modified in the loop body. - validateOperation(node, node->getOperand()); - - return true; -} - -bool ValidateLimitations::visitAggregate(Visit, TIntermAggregate* node) -{ - switch (node->getOp()) { - case EOpFunctionCall: - validateFunctionCall(node); - break; - default: - break; - } - return true; -} - -bool ValidateLimitations::visitLoop(Visit, TIntermLoop* node) -{ - if (!validateLoopType(node)) - return false; - - TLoopInfo info; - memset(&info, 0, sizeof(TLoopInfo)); - info.loop = node; - if (!validateForLoopHeader(node, &info)) - return false; - - TIntermNode* body = node->getBody(); - if (body != NULL) { - mLoopStack.push_back(info); - body->traverse(this); - mLoopStack.pop_back(); - } - - // The loop is fully processed - no need to visit children. - return false; -} - -void ValidateLimitations::error(TSourceLoc loc, - const char *reason, const char* token) -{ - mSink.prefix(EPrefixError); - mSink.location(loc); - mSink << "'" << token << "' : " << reason << "\n"; - ++mNumErrors; -} - -bool ValidateLimitations::withinLoopBody() const -{ - return !mLoopStack.empty(); -} - -bool ValidateLimitations::isLoopIndex(const TIntermSymbol* symbol) const -{ - return IsLoopIndex(symbol, mLoopStack); -} - -bool ValidateLimitations::validateLoopType(TIntermLoop* node) { - TLoopType type = node->getType(); - if (type == ELoopFor) - return true; - - // Reject while and do-while loops. - error(node->getLine(), - "This type of loop is not allowed", - type == ELoopWhile ? "while" : "do"); - return false; -} - -bool ValidateLimitations::validateForLoopHeader(TIntermLoop* node, - TLoopInfo* info) -{ - ASSERT(node->getType() == ELoopFor); - - // - // The for statement has the form: - // for ( init-declaration ; condition ; expression ) statement - // - if (!validateForLoopInit(node, info)) - return false; - if (!validateForLoopCond(node, info)) - return false; - if (!validateForLoopExpr(node, info)) - return false; - - return true; -} - -bool ValidateLimitations::validateForLoopInit(TIntermLoop* node, - TLoopInfo* info) -{ - TIntermNode* init = node->getInit(); - if (init == NULL) { - error(node->getLine(), "Missing init declaration", "for"); - return false; - } - - // - // init-declaration has the form: - // type-specifier identifier = constant-expression - // - TIntermAggregate* decl = init->getAsAggregate(); - if ((decl == NULL) || (decl->getOp() != EOpDeclaration)) { - error(init->getLine(), "Invalid init declaration", "for"); - return false; - } - // To keep things simple do not allow declaration list. - TIntermSequence& declSeq = decl->getSequence(); - if (declSeq.size() != 1) { - error(decl->getLine(), "Invalid init declaration", "for"); - return false; - } - TIntermBinary* declInit = declSeq[0]->getAsBinaryNode(); - if ((declInit == NULL) || (declInit->getOp() != EOpInitialize)) { - error(decl->getLine(), "Invalid init declaration", "for"); - return false; - } - TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode(); - if (symbol == NULL) { - error(declInit->getLine(), "Invalid init declaration", "for"); - return false; - } - // The loop index has type int or float. - TBasicType type = symbol->getBasicType(); - if ((type != EbtInt) && (type != EbtFloat)) { - error(symbol->getLine(), - "Invalid type for loop index", getBasicString(type)); - return false; - } - // The loop index is initialized with constant expression. - if (!isConstExpr(declInit->getRight())) { - error(declInit->getLine(), - "Loop index cannot be initialized with non-constant expression", - symbol->getSymbol().c_str()); - return false; - } - - info->index.id = symbol->getId(); - return true; -} - -bool ValidateLimitations::validateForLoopCond(TIntermLoop* node, - TLoopInfo* info) -{ - TIntermNode* cond = node->getCondition(); - if (cond == NULL) { - error(node->getLine(), "Missing condition", "for"); - return false; - } - // - // condition has the form: - // loop_index relational_operator constant_expression - // - TIntermBinary* binOp = cond->getAsBinaryNode(); - if (binOp == NULL) { - error(node->getLine(), "Invalid condition", "for"); - return false; - } - // Loop index should be to the left of relational operator. - TIntermSymbol* symbol = binOp->getLeft()->getAsSymbolNode(); - if (symbol == NULL) { - error(binOp->getLine(), "Invalid condition", "for"); - return false; - } - if (symbol->getId() != info->index.id) { - error(symbol->getLine(), - "Expected loop index", symbol->getSymbol().c_str()); - return false; - } - // Relational operator is one of: > >= < <= == or !=. - switch (binOp->getOp()) { - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - break; - default: - error(binOp->getLine(), - "Invalid relational operator", - getOperatorString(binOp->getOp())); - break; - } - // Loop index must be compared with a constant. - if (!isConstExpr(binOp->getRight())) { - error(binOp->getLine(), - "Loop index cannot be compared with non-constant expression", - symbol->getSymbol().c_str()); - return false; - } - - return true; -} - -bool ValidateLimitations::validateForLoopExpr(TIntermLoop* node, - TLoopInfo* info) -{ - TIntermNode* expr = node->getExpression(); - if (expr == NULL) { - error(node->getLine(), "Missing expression", "for"); - return false; - } - - // for expression has one of the following forms: - // loop_index++ - // loop_index-- - // loop_index += constant_expression - // loop_index -= constant_expression - // ++loop_index - // --loop_index - // The last two forms are not specified in the spec, but I am assuming - // its an oversight. - TIntermUnary* unOp = expr->getAsUnaryNode(); - TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode(); - - TOperator op = EOpNull; - TIntermSymbol* symbol = NULL; - if (unOp != NULL) { - op = unOp->getOp(); - symbol = unOp->getOperand()->getAsSymbolNode(); - } else if (binOp != NULL) { - op = binOp->getOp(); - symbol = binOp->getLeft()->getAsSymbolNode(); - } - - // The operand must be loop index. - if (symbol == NULL) { - error(expr->getLine(), "Invalid expression", "for"); - return false; - } - if (symbol->getId() != info->index.id) { - error(symbol->getLine(), - "Expected loop index", symbol->getSymbol().c_str()); - return false; - } - - // The operator is one of: ++ -- += -=. - switch (op) { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - ASSERT((unOp != NULL) && (binOp == NULL)); - break; - case EOpAddAssign: - case EOpSubAssign: - ASSERT((unOp == NULL) && (binOp != NULL)); - break; - default: - error(expr->getLine(), "Invalid operator", getOperatorString(op)); - return false; - } - - // Loop index must be incremented/decremented with a constant. - if (binOp != NULL) { - if (!isConstExpr(binOp->getRight())) { - error(binOp->getLine(), - "Loop index cannot be modified by non-constant expression", - symbol->getSymbol().c_str()); - return false; - } - } - - return true; -} - -bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node) -{ - ASSERT(node->getOp() == EOpFunctionCall); - - // If not within loop body, there is nothing to check. - if (!withinLoopBody()) - return true; - - // List of param indices for which loop indices are used as argument. - typedef std::vector 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 = GetGlobalParseContext()->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/src/3rdparty/angle/src/compiler/ValidateLimitations.h b/src/3rdparty/angle/src/compiler/ValidateLimitations.h deleted file mode 100644 index a835cb3c22..0000000000 --- a/src/3rdparty/angle/src/compiler/ValidateLimitations.h +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "GLSLANG/ShaderLang.h" -#include "compiler/intermediate.h" - -class TInfoSinkBase; - -struct TLoopInfo { - struct TIndex { - int id; // symbol id. - } index; - TIntermLoop* loop; -}; -typedef TVector TLoopStack; - -// Traverses intermediate tree to ensure that the shader does not exceed the -// minimum functionality mandated in GLSL 1.0 spec, Appendix A. -class ValidateLimitations : public TIntermTraverser { -public: - ValidateLimitations(ShShaderType shaderType, TInfoSinkBase& sink); - - int numErrors() const { return mNumErrors; } - - virtual bool visitBinary(Visit, TIntermBinary*); - virtual bool visitUnary(Visit, TIntermUnary*); - virtual bool visitAggregate(Visit, TIntermAggregate*); - virtual bool visitLoop(Visit, TIntermLoop*); - -private: - void error(TSourceLoc loc, const char *reason, const char* token); - - bool withinLoopBody() const; - bool isLoopIndex(const TIntermSymbol* symbol) const; - bool validateLoopType(TIntermLoop* node); - bool validateForLoopHeader(TIntermLoop* node, TLoopInfo* info); - bool validateForLoopInit(TIntermLoop* node, TLoopInfo* info); - bool validateForLoopCond(TIntermLoop* node, TLoopInfo* info); - bool validateForLoopExpr(TIntermLoop* node, TLoopInfo* info); - // Returns true if none of the loop indices is used as the argument to - // the given function out or inout parameter. - bool validateFunctionCall(TIntermAggregate* node); - bool validateOperation(TIntermOperator* node, TIntermNode* operand); - - // Returns true if indexing does not exceed the minimum functionality - // mandated in GLSL 1.0 spec, Appendix A, Section 5. - bool isConstExpr(TIntermNode* node); - bool isConstIndexExpr(TIntermNode* node); - bool validateIndexing(TIntermBinary* node); - - ShShaderType mShaderType; - TInfoSinkBase& mSink; - int mNumErrors; - TLoopStack mLoopStack; -}; - diff --git a/src/3rdparty/angle/src/compiler/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/VariableInfo.cpp deleted file mode 100644 index f3f7b1ef35..0000000000 --- a/src/3rdparty/angle/src/compiler/VariableInfo.cpp +++ /dev/null @@ -1,308 +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. -// - -#include "compiler/VariableInfo.h" - -namespace { - -TString arrayBrackets(int index) -{ - TStringStream stream; - stream << "[" << index << "]"; - return stream.str(); -} - -// Returns the data type for an attribute, uniform, or varying. -ShDataType getVariableDataType(const TType& type) -{ - switch (type.getBasicType()) { - case EbtFloat: - if (type.isMatrix()) { - switch (type.getNominalSize()) { - case 2: return SH_FLOAT_MAT2; - case 3: return SH_FLOAT_MAT3; - case 4: return SH_FLOAT_MAT4; - default: UNREACHABLE(); - } - } else if (type.isVector()) { - switch (type.getNominalSize()) { - case 2: return SH_FLOAT_VEC2; - case 3: return SH_FLOAT_VEC3; - case 4: return SH_FLOAT_VEC4; - default: UNREACHABLE(); - } - } else { - return SH_FLOAT; - } - case EbtInt: - if (type.isMatrix()) { - UNREACHABLE(); - } else if (type.isVector()) { - switch (type.getNominalSize()) { - case 2: return SH_INT_VEC2; - case 3: return SH_INT_VEC3; - case 4: return SH_INT_VEC4; - default: UNREACHABLE(); - } - } else { - return SH_INT; - } - case EbtBool: - if (type.isMatrix()) { - UNREACHABLE(); - } else if (type.isVector()) { - switch (type.getNominalSize()) { - case 2: return SH_BOOL_VEC2; - case 3: return SH_BOOL_VEC3; - case 4: return SH_BOOL_VEC4; - default: UNREACHABLE(); - } - } else { - return SH_BOOL; - } - case EbtSampler2D: return SH_SAMPLER_2D; - case EbtSamplerCube: return SH_SAMPLER_CUBE; - case EbtSamplerExternalOES: return SH_SAMPLER_EXTERNAL_OES; - case EbtSampler2DRect: return SH_SAMPLER_2D_RECT_ARB; - default: UNREACHABLE(); - } - return SH_NONE; -} - -void getBuiltInVariableInfo(const TType& type, - const TString& name, - const TString& mappedName, - TVariableInfoList& infoList); -void getUserDefinedVariableInfo(const TType& type, - const TString& name, - const TString& mappedName, - TVariableInfoList& infoList, - ShHashFunction64 hashFunction); - -// Returns info for an attribute, uniform, or varying. -void getVariableInfo(const TType& type, - const TString& name, - const TString& mappedName, - TVariableInfoList& infoList, - ShHashFunction64 hashFunction) -{ - if (type.getBasicType() == EbtStruct) { - if (type.isArray()) { - for (int i = 0; i < type.getArraySize(); ++i) { - TString lname = name + arrayBrackets(i); - TString lmappedName = mappedName + arrayBrackets(i); - getUserDefinedVariableInfo(type, lname, lmappedName, infoList, hashFunction); - } - } else { - getUserDefinedVariableInfo(type, name, mappedName, infoList, hashFunction); - } - } else { - getBuiltInVariableInfo(type, name, mappedName, infoList); - } -} - -void getBuiltInVariableInfo(const TType& type, - const TString& name, - const TString& mappedName, - TVariableInfoList& infoList) -{ - ASSERT(type.getBasicType() != EbtStruct); - - TVariableInfo varInfo; - if (type.isArray()) { - varInfo.name = (name + "[0]").c_str(); - varInfo.mappedName = (mappedName + "[0]").c_str(); - varInfo.size = type.getArraySize(); - } else { - varInfo.name = name.c_str(); - varInfo.mappedName = mappedName.c_str(); - varInfo.size = 1; - } - varInfo.precision = type.getPrecision(); - varInfo.type = getVariableDataType(type); - infoList.push_back(varInfo); -} - -void getUserDefinedVariableInfo(const TType& type, - const TString& name, - const TString& mappedName, - TVariableInfoList& infoList, - ShHashFunction64 hashFunction) -{ - ASSERT(type.getBasicType() == EbtStruct); - - const TFieldList& fields = type.getStruct()->fields(); - for (size_t i = 0; i < fields.size(); ++i) { - const TType& fieldType = *(fields[i]->type()); - const TString& fieldName = fields[i]->name(); - getVariableInfo(fieldType, - name + "." + fieldName, - mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction), - infoList, - hashFunction); - } -} - -TVariableInfo* findVariable(const TType& type, - const TString& name, - TVariableInfoList& infoList) -{ - // TODO(zmo): optimize this function. - TString myName = name; - if (type.isArray()) - myName += "[0]"; - for (size_t ii = 0; ii < infoList.size(); ++ii) - { - if (infoList[ii].name.c_str() == myName) - return &(infoList[ii]); - } - return NULL; -} - -} // namespace anonymous - -TVariableInfo::TVariableInfo() - : type(SH_NONE), - size(0), - precision(EbpUndefined), - staticUse(false) -{ -} - -TVariableInfo::TVariableInfo(ShDataType type, int size) - : type(type), - size(size), - precision(EbpUndefined), - staticUse(false) -{ -} - -CollectVariables::CollectVariables(TVariableInfoList& attribs, - TVariableInfoList& uniforms, - TVariableInfoList& varyings, - ShHashFunction64 hashFunction) - : mAttribs(attribs), - mUniforms(uniforms), - mVaryings(varyings), - mPointCoordAdded(false), - mFrontFacingAdded(false), - mFragCoordAdded(false), - mHashFunction(hashFunction) -{ -} - -// We want to check whether a uniform/varying is statically used -// because we only count the used ones in packing computing. -// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count -// toward varying counting if they are statically used in a fragment -// shader. -void CollectVariables::visitSymbol(TIntermSymbol* symbol) -{ - ASSERT(symbol != NULL); - TVariableInfo* var = NULL; - switch (symbol->getQualifier()) - { - case EvqVaryingOut: - case EvqInvariantVaryingOut: - case EvqVaryingIn: - case EvqInvariantVaryingIn: - var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings); - break; - case EvqUniform: - var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms); - break; - case EvqFragCoord: - if (!mFragCoordAdded) { - TVariableInfo info; - info.name = "gl_FragCoord"; - info.mappedName = "gl_FragCoord"; - info.type = SH_FLOAT_VEC4; - info.size = 1; - info.precision = EbpMedium; // Use mediump as it doesn't really matter. - info.staticUse = true; - mVaryings.push_back(info); - mFragCoordAdded = true; - } - return; - case EvqFrontFacing: - if (!mFrontFacingAdded) { - TVariableInfo info; - info.name = "gl_FrontFacing"; - info.mappedName = "gl_FrontFacing"; - info.type = SH_BOOL; - info.size = 1; - info.precision = EbpUndefined; - info.staticUse = true; - mVaryings.push_back(info); - mFrontFacingAdded = true; - } - return; - case EvqPointCoord: - if (!mPointCoordAdded) { - TVariableInfo info; - info.name = "gl_PointCoord"; - info.mappedName = "gl_PointCoord"; - info.type = SH_FLOAT_VEC2; - info.size = 1; - info.precision = EbpMedium; // Use mediump as it doesn't really matter. - info.staticUse = true; - mVaryings.push_back(info); - mPointCoordAdded = true; - } - return; - default: - break; - } - if (var) - var->staticUse = true; -} - -bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node) -{ - bool visitChildren = true; - - switch (node->getOp()) - { - case EOpDeclaration: { - const TIntermSequence& sequence = node->getSequence(); - TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier(); - if (qualifier == EvqAttribute || qualifier == EvqUniform || - qualifier == EvqVaryingIn || qualifier == EvqVaryingOut || - qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut) - { - TVariableInfoList& infoList = qualifier == EvqAttribute ? mAttribs : - (qualifier == EvqUniform ? mUniforms : mVaryings); - 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, uniforms, - // and varyings cannot be initialized in a shader, we must have - // only TIntermSymbol nodes in the sequence. - ASSERT(variable != NULL); - TString processedSymbol; - if (mHashFunction == NULL) - processedSymbol = variable->getSymbol(); - else - processedSymbol = TIntermTraverser::hash(variable->getOriginalSymbol(), mHashFunction); - getVariableInfo(variable->getType(), - variable->getOriginalSymbol(), - processedSymbol, - infoList, - mHashFunction); - visitChildren = false; - } - } - break; - } - default: break; - } - - return visitChildren; -} - diff --git a/src/3rdparty/angle/src/compiler/VariableInfo.h b/src/3rdparty/angle/src/compiler/VariableInfo.h deleted file mode 100644 index 3c7f2a5f84..0000000000 --- a/src/3rdparty/angle/src/compiler/VariableInfo.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_VARIABLE_INFO_H_ -#define COMPILER_VARIABLE_INFO_H_ - -#include "GLSLANG/ShaderLang.h" -#include "compiler/intermediate.h" - -// Provides information about a variable. -// It is currently being used to store info about active attribs and uniforms. -struct TVariableInfo { - TVariableInfo(ShDataType type, int size); - TVariableInfo(); - - TPersistString name; - TPersistString mappedName; - ShDataType type; - int size; - TPrecision precision; - bool staticUse; -}; -typedef std::vector TVariableInfoList; - -// Traverses intermediate tree to collect all attributes, uniforms, varyings. -class CollectVariables : public TIntermTraverser { -public: - CollectVariables(TVariableInfoList& attribs, - TVariableInfoList& uniforms, - TVariableInfoList& varyings, - ShHashFunction64 hashFunction); - - virtual void visitSymbol(TIntermSymbol*); - virtual bool visitAggregate(Visit, TIntermAggregate*); - -private: - TVariableInfoList& mAttribs; - TVariableInfoList& mUniforms; - TVariableInfoList& mVaryings; - - bool mPointCoordAdded; - bool mFrontFacingAdded; - bool mFragCoordAdded; - - ShHashFunction64 mHashFunction; -}; - -#endif // COMPILER_VARIABLE_INFO_H_ diff --git a/src/3rdparty/angle/src/compiler/VariablePacker.cpp b/src/3rdparty/angle/src/compiler/VariablePacker.cpp deleted file mode 100644 index 8957287763..0000000000 --- a/src/3rdparty/angle/src/compiler/VariablePacker.cpp +++ /dev/null @@ -1,297 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -#include "compiler/VariablePacker.h" - -#include -#include "compiler/ShHandle.h" - -namespace { -int GetSortOrder(ShDataType type) -{ - switch (type) { - case SH_FLOAT_MAT4: - return 0; - case SH_FLOAT_MAT2: - return 1; - case SH_FLOAT_VEC4: - case SH_INT_VEC4: - case SH_BOOL_VEC4: - return 2; - case SH_FLOAT_MAT3: - return 3; - case SH_FLOAT_VEC3: - case SH_INT_VEC3: - case SH_BOOL_VEC3: - return 4; - case SH_FLOAT_VEC2: - case SH_INT_VEC2: - case SH_BOOL_VEC2: - return 5; - case SH_FLOAT: - case SH_INT: - case SH_BOOL: - case SH_SAMPLER_2D: - case SH_SAMPLER_CUBE: - case SH_SAMPLER_EXTERNAL_OES: - case SH_SAMPLER_2D_RECT_ARB: - return 6; - default: - ASSERT(false); - return 7; - } -} -} // namespace - -int VariablePacker::GetNumComponentsPerRow(ShDataType type) -{ - switch (type) { - case SH_FLOAT_MAT4: - case SH_FLOAT_MAT2: - case SH_FLOAT_VEC4: - case SH_INT_VEC4: - case SH_BOOL_VEC4: - return 4; - case SH_FLOAT_MAT3: - case SH_FLOAT_VEC3: - case SH_INT_VEC3: - case SH_BOOL_VEC3: - return 3; - case SH_FLOAT_VEC2: - case SH_INT_VEC2: - case SH_BOOL_VEC2: - return 2; - case SH_FLOAT: - case SH_INT: - case SH_BOOL: - case SH_SAMPLER_2D: - case SH_SAMPLER_CUBE: - case SH_SAMPLER_EXTERNAL_OES: - case SH_SAMPLER_2D_RECT_ARB: - return 1; - default: - ASSERT(false); - return 5; - } -} - -int VariablePacker::GetNumRows(ShDataType type) -{ - switch (type) { - case SH_FLOAT_MAT4: - return 4; - case SH_FLOAT_MAT3: - return 3; - case SH_FLOAT_MAT2: - return 2; - case SH_FLOAT_VEC4: - case SH_INT_VEC4: - case SH_BOOL_VEC4: - case SH_FLOAT_VEC3: - case SH_INT_VEC3: - case SH_BOOL_VEC3: - case SH_FLOAT_VEC2: - case SH_INT_VEC2: - case SH_BOOL_VEC2: - case SH_FLOAT: - case SH_INT: - case SH_BOOL: - case SH_SAMPLER_2D: - case SH_SAMPLER_CUBE: - case SH_SAMPLER_EXTERNAL_OES: - case SH_SAMPLER_2D_RECT_ARB: - return 1; - default: - ASSERT(false); - return 100000; - } -} - -struct TVariableInfoComparer { - bool operator()(const TVariableInfo& lhs, const TVariableInfo& rhs) const - { - int lhsSortOrder = GetSortOrder(lhs.type); - int rhsSortOrder = GetSortOrder(rhs.type); - if (lhsSortOrder != rhsSortOrder) { - return lhsSortOrder < rhsSortOrder; - } - // Sort by largest first. - return lhs.size > rhs.size; - } -}; - -unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow) -{ - return ((kColumnMask << (kNumColumns - numComponentsPerRow)) & - kColumnMask) >> column; -} - -void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow) -{ - unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow); - for (int r = 0; r < numRows; ++r) { - int row = topRow + r; - ASSERT((rows_[row] & columnFlags) == 0); - rows_[row] |= columnFlags; - } -} - -bool VariablePacker::searchColumn(int column, int numRows, int* destRow, int* destSize) -{ - ASSERT(destRow); - - for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask; - ++topNonFullRow_) { - } - - for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask; - --bottomNonFullRow_) { - } - - if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows) { - return false; - } - - unsigned columnFlags = makeColumnFlags(column, 1); - int topGoodRow = 0; - int smallestGoodTop = -1; - int smallestGoodSize = maxRows_ + 1; - int bottomRow = bottomNonFullRow_ + 1; - bool found = false; - for (int row = topNonFullRow_; row <= bottomRow; ++row) { - bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false; - if (rowEmpty) { - if (!found) { - topGoodRow = row; - found = true; - } - } else { - if (found) { - int size = row - topGoodRow; - if (size >= numRows && size < smallestGoodSize) { - smallestGoodSize = size; - smallestGoodTop = topGoodRow; - } - } - found = false; - } - } - if (smallestGoodTop < 0) { - return false; - } - - *destRow = smallestGoodTop; - if (destSize) { - *destSize = smallestGoodSize; - } - return true; -} - -bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVariableInfoList& in_variables) -{ - ASSERT(maxVectors > 0); - maxRows_ = maxVectors; - topNonFullRow_ = 0; - bottomNonFullRow_ = maxRows_ - 1; - TVariableInfoList variables(in_variables); - - // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific - // order by type, then by size of array, largest first. - std::sort(variables.begin(), variables.end(), TVariableInfoComparer()); - rows_.clear(); - rows_.resize(maxVectors, 0); - - // Packs the 4 column variables. - size_t ii = 0; - for (; ii < variables.size(); ++ii) { - const TVariableInfo& variable = variables[ii]; - if (GetNumComponentsPerRow(variable.type) != 4) { - break; - } - topNonFullRow_ += GetNumRows(variable.type) * variable.size; - } - - if (topNonFullRow_ > maxRows_) { - return false; - } - - // Packs the 3 column variables. - int num3ColumnRows = 0; - for (; ii < variables.size(); ++ii) { - const TVariableInfo& variable = variables[ii]; - if (GetNumComponentsPerRow(variable.type) != 3) { - break; - } - num3ColumnRows += GetNumRows(variable.type) * variable.size; - } - - if (topNonFullRow_ + num3ColumnRows > maxRows_) { - return false; - } - - fillColumns(topNonFullRow_, num3ColumnRows, 0, 3); - - // Packs the 2 column variables. - int top2ColumnRow = topNonFullRow_ + num3ColumnRows; - int twoColumnRowsAvailable = maxRows_ - top2ColumnRow; - int rowsAvailableInColumns01 = twoColumnRowsAvailable; - int rowsAvailableInColumns23 = twoColumnRowsAvailable; - for (; ii < variables.size(); ++ii) { - const TVariableInfo& variable = variables[ii]; - if (GetNumComponentsPerRow(variable.type) != 2) { - break; - } - int numRows = GetNumRows(variable.type) * variable.size; - if (numRows <= rowsAvailableInColumns01) { - rowsAvailableInColumns01 -= numRows; - } else if (numRows <= rowsAvailableInColumns23) { - rowsAvailableInColumns23 -= numRows; - } else { - return false; - } - } - - int numRowsUsedInColumns01 = - twoColumnRowsAvailable - rowsAvailableInColumns01; - int numRowsUsedInColumns23 = - twoColumnRowsAvailable - rowsAvailableInColumns23; - fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2); - fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23, - 2, 2); - - // Packs the 1 column variables. - for (; ii < variables.size(); ++ii) { - const TVariableInfo& variable = variables[ii]; - ASSERT(1 == GetNumComponentsPerRow(variable.type)); - int numRows = GetNumRows(variable.type) * variable.size; - int smallestColumn = -1; - int smallestSize = maxRows_ + 1; - int topRow = -1; - for (int column = 0; column < kNumColumns; ++column) { - int row = 0; - int size = 0; - if (searchColumn(column, numRows, &row, &size)) { - if (size < smallestSize) { - smallestSize = size; - smallestColumn = column; - topRow = row; - } - } - } - - if (smallestColumn < 0) { - return false; - } - - fillColumns(topRow, numRows, smallestColumn, 1); - } - - ASSERT(variables.size() == ii); - - return true; -} - - - diff --git a/src/3rdparty/angle/src/compiler/VariablePacker.h b/src/3rdparty/angle/src/compiler/VariablePacker.h deleted file mode 100644 index 8987066cc3..0000000000 --- a/src/3rdparty/angle/src/compiler/VariablePacker.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef _VARIABLEPACKER_INCLUDED_ -#define _VARIABLEPACKER_INCLUDED_ - -#include -#include "compiler/ShHandle.h" - -class VariablePacker { - public: - // Returns true if the passed in variables pack in maxVectors following - // the packing rules from the GLSL 1.017 spec, Appendix A, section 7. - bool CheckVariablesWithinPackingLimits( - int maxVectors, - const TVariableInfoList& in_variables); - - // Gets how many components in a row a data type takes. - static int GetNumComponentsPerRow(ShDataType type); - - // Gets how many rows a data type takes. - static int GetNumRows(ShDataType type); - - private: - static const int kNumColumns = 4; - static const unsigned kColumnMask = (1 << kNumColumns) - 1; - - unsigned makeColumnFlags(int column, int numComponentsPerRow); - void fillColumns(int topRow, int numRows, int column, int numComponentsPerRow); - bool searchColumn(int column, int numRows, int* destRow, int* destSize); - - int topNonFullRow_; - int bottomNonFullRow_; - int maxRows_; - std::vector rows_; -}; - -#endif // _VARIABLEPACKER_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/VersionGLSL.cpp deleted file mode 100644 index 7a82bb4dc1..0000000000 --- a/src/3rdparty/angle/src/compiler/VersionGLSL.cpp +++ /dev/null @@ -1,140 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/VersionGLSL.h" - -static const int GLSL_VERSION_110 = 110; -static const int GLSL_VERSION_120 = 120; - -// We need to scan for the following: -// 1. "invariant" keyword: This can occur in both - vertex and fragment shaders -// but only at the global scope. -// 2. "gl_PointCoord" built-in variable: This can only occur in fragment shader -// but inside any scope. -// 3. Call to a matrix constructor with another matrix as argument. -// (These constructors were reserved in GLSL version 1.10.) -// 4. Arrays as "out" function parameters. -// GLSL spec section 6.1.1: "When calling a function, expressions that do -// not evaluate to l-values cannot be passed to parameters declared as -// out or inout." -// GLSL 1.1 section 5.8: "Other binary or unary expressions, -// non-dereferenced arrays, function names, swizzles with repeated fields, -// and constants cannot be l-values." -// GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that -// are built-in types, entire structures or arrays... are all l-values." -// -// TODO(alokp): The following two cases of invariant decalaration get lost -// during parsing - they do not get carried over to the intermediate tree. -// Handle these cases: -// 1. When a pragma is used to force all output variables to be invariant: -// - #pragma STDGL invariant(all) -// 2. When a previously decalared or built-in variable is marked invariant: -// - invariant gl_Position; -// - varying vec3 color; invariant color; -// -TVersionGLSL::TVersionGLSL(ShShaderType type) - : mShaderType(type), - mVersion(GLSL_VERSION_110) -{ -} - -void TVersionGLSL::visitSymbol(TIntermSymbol* node) -{ - if (node->getSymbol() == "gl_PointCoord") - updateVersion(GLSL_VERSION_120); -} - -void TVersionGLSL::visitConstantUnion(TIntermConstantUnion*) -{ -} - -bool TVersionGLSL::visitBinary(Visit, TIntermBinary*) -{ - return true; -} - -bool TVersionGLSL::visitUnary(Visit, TIntermUnary*) -{ - return true; -} - -bool TVersionGLSL::visitSelection(Visit, TIntermSelection*) -{ - return true; -} - -bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate* node) -{ - bool visitChildren = true; - - switch (node->getOp()) { - case EOpSequence: - // We need to visit sequence children to get to global or inner scope. - visitChildren = true; - break; - case EOpDeclaration: { - const TIntermSequence& sequence = node->getSequence(); - TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier(); - if ((qualifier == EvqInvariantVaryingIn) || - (qualifier == EvqInvariantVaryingOut)) { - updateVersion(GLSL_VERSION_120); - } - break; - } - case EOpParameters: { - const TIntermSequence& params = node->getSequence(); - for (TIntermSequence::const_iterator iter = params.begin(); - iter != params.end(); ++iter) - { - const TIntermTyped* param = (*iter)->getAsTyped(); - if (param->isArray()) - { - TQualifier qualifier = param->getQualifier(); - if ((qualifier == EvqOut) || (qualifier == EvqInOut)) - { - updateVersion(GLSL_VERSION_120); - break; - } - } - } - // Fully processed. No need to visit children. - visitChildren = false; - break; - } - case EOpConstructMat2: - case EOpConstructMat3: - case EOpConstructMat4: { - const TIntermSequence& sequence = node->getSequence(); - if (sequence.size() == 1) { - TIntermTyped* typed = sequence.front()->getAsTyped(); - if (typed && typed->isMatrix()) { - updateVersion(GLSL_VERSION_120); - } - } - break; - } - - default: break; - } - - return visitChildren; -} - -bool TVersionGLSL::visitLoop(Visit, TIntermLoop*) -{ - return true; -} - -bool TVersionGLSL::visitBranch(Visit, TIntermBranch*) -{ - return true; -} - -void TVersionGLSL::updateVersion(int version) -{ - mVersion = std::max(version, mVersion); -} - diff --git a/src/3rdparty/angle/src/compiler/VersionGLSL.h b/src/3rdparty/angle/src/compiler/VersionGLSL.h deleted file mode 100644 index 1c1cb1ab97..0000000000 --- a/src/3rdparty/angle/src/compiler/VersionGLSL.h +++ /dev/null @@ -1,56 +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. -// - -#ifndef COMPILER_VERSIONGLSL_H_ -#define COMPILER_VERSIONGLSL_H_ - -#include "GLSLANG/ShaderLang.h" -#include "compiler/intermediate.h" - -// Traverses the intermediate tree to return the minimum GLSL version -// required to legally access all built-in features used in the shader. -// GLSL 1.1 which is mandated by OpenGL 2.0 provides: -// - #version and #extension to declare version and extensions. -// - built-in functions refract, exp, and log. -// - updated step() to compare x < edge instead of x <= edge. -// GLSL 1.2 which is mandated by OpenGL 2.1 provides: -// - many changes to reduce differences when compared to the ES specification. -// - invariant keyword and its support. -// - c++ style name hiding rules. -// - built-in variable gl_PointCoord for fragment shaders. -// - matrix constructors taking matrix as argument. -// - array as "out" function parameters -// -class TVersionGLSL : public TIntermTraverser { -public: - TVersionGLSL(ShShaderType type); - - // Returns 120 if the following is used the shader: - // - "invariant", - // - "gl_PointCoord", - // - matrix/matrix constructors - // - array "out" parameters - // Else 110 is returned. - int getVersion() { return mVersion; } - - virtual void visitSymbol(TIntermSymbol*); - virtual void visitConstantUnion(TIntermConstantUnion*); - virtual bool visitBinary(Visit, TIntermBinary*); - virtual bool visitUnary(Visit, TIntermUnary*); - virtual bool visitSelection(Visit, TIntermSelection*); - virtual bool visitAggregate(Visit, TIntermAggregate*); - virtual bool visitLoop(Visit, TIntermLoop*); - virtual bool visitBranch(Visit, TIntermBranch*); - -protected: - void updateVersion(int version); - -private: - ShShaderType mShaderType; - int mVersion; -}; - -#endif // COMPILER_VERSIONGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/debug.cpp b/src/3rdparty/angle/src/compiler/debug.cpp deleted file mode 100644 index 53778bd3eb..0000000000 --- a/src/3rdparty/angle/src/compiler/debug.cpp +++ /dev/null @@ -1,37 +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. -// - -// debug.cpp: Debugging utilities. - -#include "compiler/debug.h" - -#include -#include - -#include "compiler/InitializeParseContext.h" -#include "compiler/ParseHelper.h" - -static const int kTraceBufferLen = 1024; - -#ifdef TRACE_ENABLED -extern "C" { -void Trace(const char *format, ...) { - if (!format) return; - - TParseContext* parseContext = GetGlobalParseContext(); - if (parseContext) { - char buf[kTraceBufferLen]; - va_list args; - va_start(args, format); - vsnprintf(buf, kTraceBufferLen, format, args); - va_end(args); - - parseContext->trace(buf); - } -} -} // extern "C" -#endif // TRACE_ENABLED - diff --git a/src/3rdparty/angle/src/compiler/debug.h b/src/3rdparty/angle/src/compiler/debug.h deleted file mode 100644 index 7a371516af..0000000000 --- a/src/3rdparty/angle/src/compiler/debug.h +++ /dev/null @@ -1,53 +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. -// - -// debug.h: Debugging utilities. - -#ifndef COMPILER_DEBUG_H_ -#define COMPILER_DEBUG_H_ - -#include - -#ifdef _DEBUG -#define TRACE_ENABLED // define to enable debug message tracing -#endif // _DEBUG - -// Outputs text to the debug log -#ifdef TRACE_ENABLED - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus -void Trace(const char* format, ...); -#ifdef __cplusplus -} -#endif // __cplusplus - -#else // TRACE_ENABLED - -#define Trace(...) ((void)0) - -#endif // TRACE_ENABLED - -// A macro asserting a condition and outputting failures to the debug log -#define ASSERT(expression) do { \ - if(!(expression)) \ - Trace("Assert failed: %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \ - assert(expression); \ -} while(0) - -#define UNIMPLEMENTED() do { \ - Trace("Unimplemented invoked: %s(%d)\n", __FUNCTION__, __LINE__); \ - assert(false); \ -} while(0) - -#define UNREACHABLE() do { \ - Trace("Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \ - assert(false); \ -} while(0) - -#endif // COMPILER_DEBUG_H_ - diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.cpp b/src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.cpp deleted file mode 100644 index ca661d6767..0000000000 --- a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#pragma warning(disable: 4718) - -#include "compiler/depgraph/DependencyGraph.h" -#include "compiler/depgraph/DependencyGraphBuilder.h" - -TDependencyGraph::TDependencyGraph(TIntermNode* intermNode) -{ - TDependencyGraphBuilder::build(intermNode, this); -} - -TDependencyGraph::~TDependencyGraph() -{ - for (TGraphNodeVector::const_iterator iter = mAllNodes.begin(); iter != mAllNodes.end(); ++iter) - { - TGraphNode* node = *iter; - delete node; - } -} - -TGraphArgument* TDependencyGraph::createArgument(TIntermAggregate* intermFunctionCall, - int argumentNumber) -{ - TGraphArgument* argument = new TGraphArgument(intermFunctionCall, argumentNumber); - mAllNodes.push_back(argument); - return argument; -} - -TGraphFunctionCall* TDependencyGraph::createFunctionCall(TIntermAggregate* intermFunctionCall) -{ - TGraphFunctionCall* functionCall = new TGraphFunctionCall(intermFunctionCall); - mAllNodes.push_back(functionCall); - if (functionCall->getIntermFunctionCall()->isUserDefined()) - mUserDefinedFunctionCalls.push_back(functionCall); - return functionCall; -} - -TGraphSymbol* TDependencyGraph::getOrCreateSymbol(TIntermSymbol* intermSymbol) -{ - TSymbolIdMap::const_iterator iter = mSymbolIdMap.find(intermSymbol->getId()); - - TGraphSymbol* symbol = NULL; - - if (iter != mSymbolIdMap.end()) { - TSymbolIdPair pair = *iter; - symbol = pair.second; - } else { - symbol = new TGraphSymbol(intermSymbol); - mAllNodes.push_back(symbol); - - TSymbolIdPair pair(intermSymbol->getId(), symbol); - mSymbolIdMap.insert(pair); - - // We save all sampler symbols in a collection, so we can start graph traversals from them quickly. - if (IsSampler(intermSymbol->getBasicType())) - mSamplerSymbols.push_back(symbol); - } - - return symbol; -} - -TGraphSelection* TDependencyGraph::createSelection(TIntermSelection* intermSelection) -{ - TGraphSelection* selection = new TGraphSelection(intermSelection); - mAllNodes.push_back(selection); - return selection; -} - -TGraphLoop* TDependencyGraph::createLoop(TIntermLoop* intermLoop) -{ - TGraphLoop* loop = new TGraphLoop(intermLoop); - mAllNodes.push_back(loop); - return loop; -} - -TGraphLogicalOp* TDependencyGraph::createLogicalOp(TIntermBinary* intermLogicalOp) -{ - TGraphLogicalOp* logicalOp = new TGraphLogicalOp(intermLogicalOp); - mAllNodes.push_back(logicalOp); - return logicalOp; -} - -const char* TGraphLogicalOp::getOpString() const -{ - const char* opString = NULL; - switch (getIntermLogicalOp()->getOp()) { - case EOpLogicalAnd: opString = "and"; break; - case EOpLogicalOr: opString = "or"; break; - default: opString = "unknown"; break; - } - return opString; -} diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.h b/src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.h deleted file mode 100644 index 5a9c35d00b..0000000000 --- a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.h +++ /dev/null @@ -1,212 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H -#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H - -#include "compiler/intermediate.h" - -#include -#include - -class TGraphNode; -class TGraphParentNode; -class TGraphArgument; -class TGraphFunctionCall; -class TGraphSymbol; -class TGraphSelection; -class TGraphLoop; -class TGraphLogicalOp; -class TDependencyGraphTraverser; -class TDependencyGraphOutput; - -typedef std::set TGraphNodeSet; -typedef std::vector TGraphNodeVector; -typedef std::vector TGraphSymbolVector; -typedef std::vector TFunctionCallVector; - -// -// Base class for all dependency graph nodes. -// -class TGraphNode { -public: - TGraphNode(TIntermNode* node) : intermNode(node) {} - virtual ~TGraphNode() {} - virtual void traverse(TDependencyGraphTraverser* graphTraverser); -protected: - TIntermNode* intermNode; -}; - -// -// Base class for dependency graph nodes that may have children. -// -class TGraphParentNode : public TGraphNode { -public: - TGraphParentNode(TIntermNode* node) : TGraphNode(node) {} - virtual ~TGraphParentNode() {} - void addDependentNode(TGraphNode* node) { if (node != this) mDependentNodes.insert(node); } - virtual void traverse(TDependencyGraphTraverser* graphTraverser); -private: - TGraphNodeSet mDependentNodes; -}; - -// -// Handle function call arguments. -// -class TGraphArgument : public TGraphParentNode { -public: - TGraphArgument(TIntermAggregate* intermFunctionCall, int argumentNumber) - : TGraphParentNode(intermFunctionCall) - , mArgumentNumber(argumentNumber) {} - virtual ~TGraphArgument() {} - const TIntermAggregate* getIntermFunctionCall() const { return intermNode->getAsAggregate(); } - int getArgumentNumber() const { return mArgumentNumber; } - virtual void traverse(TDependencyGraphTraverser* graphTraverser); -private: - int mArgumentNumber; -}; - -// -// Handle function calls. -// -class TGraphFunctionCall : public TGraphParentNode { -public: - TGraphFunctionCall(TIntermAggregate* intermFunctionCall) - : TGraphParentNode(intermFunctionCall) {} - virtual ~TGraphFunctionCall() {} - const TIntermAggregate* getIntermFunctionCall() const { return intermNode->getAsAggregate(); } - virtual void traverse(TDependencyGraphTraverser* graphTraverser); -}; - -// -// Handle symbols. -// -class TGraphSymbol : public TGraphParentNode { -public: - TGraphSymbol(TIntermSymbol* intermSymbol) : TGraphParentNode(intermSymbol) {} - virtual ~TGraphSymbol() {} - const TIntermSymbol* getIntermSymbol() const { return intermNode->getAsSymbolNode(); } - virtual void traverse(TDependencyGraphTraverser* graphTraverser); -}; - -// -// Handle if statements and ternary operators. -// -class TGraphSelection : public TGraphNode { -public: - TGraphSelection(TIntermSelection* intermSelection) : TGraphNode(intermSelection) {} - virtual ~TGraphSelection() {} - const TIntermSelection* getIntermSelection() const { return intermNode->getAsSelectionNode(); } - virtual void traverse(TDependencyGraphTraverser* graphTraverser); -}; - -// -// Handle for, do-while, and while loops. -// -class TGraphLoop : public TGraphNode { -public: - TGraphLoop(TIntermLoop* intermLoop) : TGraphNode(intermLoop) {} - virtual ~TGraphLoop() {} - const TIntermLoop* getIntermLoop() const { return intermNode->getAsLoopNode(); } - virtual void traverse(TDependencyGraphTraverser* graphTraverser); -}; - -// -// Handle logical and, or. -// -class TGraphLogicalOp : public TGraphNode { -public: - TGraphLogicalOp(TIntermBinary* intermLogicalOp) : TGraphNode(intermLogicalOp) {} - virtual ~TGraphLogicalOp() {} - const TIntermBinary* getIntermLogicalOp() const { return intermNode->getAsBinaryNode(); } - const char* getOpString() const; - virtual void traverse(TDependencyGraphTraverser* graphTraverser); -}; - -// -// A dependency graph of symbols, function calls, conditions etc. -// -// This class provides an interface to the entry points of the dependency graph. -// -// Dependency graph nodes should be created by using one of the provided "create..." methods. -// This class (and nobody else) manages the memory of the created nodes. -// Nodes may not be removed after being added, so all created nodes will exist while the -// TDependencyGraph instance exists. -// -class TDependencyGraph { -public: - TDependencyGraph(TIntermNode* intermNode); - ~TDependencyGraph(); - TGraphNodeVector::const_iterator begin() const { return mAllNodes.begin(); } - TGraphNodeVector::const_iterator end() const { return mAllNodes.end(); } - - TGraphSymbolVector::const_iterator beginSamplerSymbols() const - { - return mSamplerSymbols.begin(); - } - - TGraphSymbolVector::const_iterator endSamplerSymbols() const - { - return mSamplerSymbols.end(); - } - - TFunctionCallVector::const_iterator beginUserDefinedFunctionCalls() const - { - return mUserDefinedFunctionCalls.begin(); - } - - TFunctionCallVector::const_iterator endUserDefinedFunctionCalls() const - { - return mUserDefinedFunctionCalls.end(); - } - - TGraphArgument* createArgument(TIntermAggregate* intermFunctionCall, int argumentNumber); - TGraphFunctionCall* createFunctionCall(TIntermAggregate* intermFunctionCall); - TGraphSymbol* getOrCreateSymbol(TIntermSymbol* intermSymbol); - TGraphSelection* createSelection(TIntermSelection* intermSelection); - TGraphLoop* createLoop(TIntermLoop* intermLoop); - TGraphLogicalOp* createLogicalOp(TIntermBinary* intermLogicalOp); -private: - typedef TMap TSymbolIdMap; - typedef std::pair TSymbolIdPair; - - TGraphNodeVector mAllNodes; - TGraphSymbolVector mSamplerSymbols; - TFunctionCallVector mUserDefinedFunctionCalls; - TSymbolIdMap mSymbolIdMap; -}; - -// -// For traversing the dependency graph. Users should derive from this, -// put their traversal specific data in it, and then pass it to a -// traverse method. -// -// When using this, just fill in the methods for nodes you want visited. -// -class TDependencyGraphTraverser { -public: - TDependencyGraphTraverser() : mDepth(0) {} - - virtual void visitSymbol(TGraphSymbol* symbol) {}; - virtual void visitArgument(TGraphArgument* selection) {}; - virtual void visitFunctionCall(TGraphFunctionCall* functionCall) {}; - virtual void visitSelection(TGraphSelection* selection) {}; - virtual void visitLoop(TGraphLoop* loop) {}; - virtual void visitLogicalOp(TGraphLogicalOp* logicalOp) {}; - - int getDepth() const { return mDepth; } - void incrementDepth() { ++mDepth; } - void decrementDepth() { --mDepth; } - - void clearVisited() { mVisited.clear(); } - void markVisited(TGraphNode* node) { mVisited.insert(node); } - bool isVisited(TGraphNode* node) const { return mVisited.find(node) != mVisited.end(); } -private: - int mDepth; - TGraphNodeSet mVisited; -}; - -#endif diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.cpp b/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.cpp deleted file mode 100644 index d586cfd03c..0000000000 --- a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.cpp +++ /dev/null @@ -1,227 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/depgraph/DependencyGraphBuilder.h" - -void TDependencyGraphBuilder::build(TIntermNode* node, TDependencyGraph* graph) -{ - TDependencyGraphBuilder builder(graph); - builder.build(node); -} - -bool TDependencyGraphBuilder::visitAggregate(Visit visit, TIntermAggregate* intermAggregate) -{ - switch (intermAggregate->getOp()) { - case EOpFunction: visitFunctionDefinition(intermAggregate); break; - case EOpFunctionCall: visitFunctionCall(intermAggregate); break; - default: visitAggregateChildren(intermAggregate); break; - } - - return false; -} - -void TDependencyGraphBuilder::visitFunctionDefinition(TIntermAggregate* intermAggregate) -{ - // Currently, we do not support user defined functions. - if (intermAggregate->getName() != "main(") - return; - - visitAggregateChildren(intermAggregate); -} - -// Takes an expression like "f(x)" and creates a dependency graph like -// "x -> argument 0 -> function call". -void TDependencyGraphBuilder::visitFunctionCall(TIntermAggregate* intermFunctionCall) -{ - TGraphFunctionCall* functionCall = mGraph->createFunctionCall(intermFunctionCall); - - // Run through the function call arguments. - int argumentNumber = 0; - TIntermSequence& intermArguments = intermFunctionCall->getSequence(); - for (TIntermSequence::const_iterator iter = intermArguments.begin(); - iter != intermArguments.end(); - ++iter, ++argumentNumber) - { - TNodeSetMaintainer nodeSetMaintainer(this); - - TIntermNode* intermArgument = *iter; - intermArgument->traverse(this); - - if (TParentNodeSet* argumentNodes = mNodeSets.getTopSet()) { - TGraphArgument* argument = mGraph->createArgument(intermFunctionCall, argumentNumber); - connectMultipleNodesToSingleNode(argumentNodes, argument); - argument->addDependentNode(functionCall); - } - } - - // Push the leftmost symbol of this function call into the current set of dependent symbols to - // represent the result of this function call. - // Thus, an expression like "y = f(x)" will yield a dependency graph like - // "x -> argument 0 -> function call -> y". - // This line essentially passes the function call node back up to an earlier visitAssignment - // call, which will create the connection "function call -> y". - mNodeSets.insertIntoTopSet(functionCall); -} - -void TDependencyGraphBuilder::visitAggregateChildren(TIntermAggregate* intermAggregate) -{ - TIntermSequence& sequence = intermAggregate->getSequence(); - for(TIntermSequence::const_iterator iter = sequence.begin(); iter != sequence.end(); ++iter) - { - TIntermNode* intermChild = *iter; - intermChild->traverse(this); - } -} - -void TDependencyGraphBuilder::visitSymbol(TIntermSymbol* intermSymbol) -{ - // Push this symbol into the set of dependent symbols for the current assignment or condition - // that we are traversing. - TGraphSymbol* symbol = mGraph->getOrCreateSymbol(intermSymbol); - mNodeSets.insertIntoTopSet(symbol); - - // If this symbol is the current leftmost symbol under an assignment, replace the previous - // leftmost symbol with this symbol. - if (!mLeftmostSymbols.empty() && mLeftmostSymbols.top() != &mRightSubtree) { - mLeftmostSymbols.pop(); - mLeftmostSymbols.push(symbol); - } -} - -bool TDependencyGraphBuilder::visitBinary(Visit visit, TIntermBinary* intermBinary) -{ - TOperator op = intermBinary->getOp(); - if (op == EOpInitialize || intermBinary->modifiesState()) - visitAssignment(intermBinary); - else if (op == EOpLogicalAnd || op == EOpLogicalOr) - visitLogicalOp(intermBinary); - else - visitBinaryChildren(intermBinary); - - return false; -} - -void TDependencyGraphBuilder::visitAssignment(TIntermBinary* intermAssignment) -{ - TIntermTyped* intermLeft = intermAssignment->getLeft(); - if (!intermLeft) - return; - - TGraphSymbol* leftmostSymbol = NULL; - - { - TNodeSetMaintainer nodeSetMaintainer(this); - - { - TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mLeftSubtree); - intermLeft->traverse(this); - leftmostSymbol = mLeftmostSymbols.top(); - - // After traversing the left subtree of this assignment, we should have found a real - // leftmost symbol, and the leftmost symbol should not be a placeholder. - ASSERT(leftmostSymbol != &mLeftSubtree); - ASSERT(leftmostSymbol != &mRightSubtree); - } - - if (TIntermTyped* intermRight = intermAssignment->getRight()) { - TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree); - intermRight->traverse(this); - } - - if (TParentNodeSet* assignmentNodes = mNodeSets.getTopSet()) - connectMultipleNodesToSingleNode(assignmentNodes, leftmostSymbol); - } - - // Push the leftmost symbol of this assignment into the current set of dependent symbols to - // represent the result of this assignment. - // An expression like "a = (b = c)" will yield a dependency graph like "c -> b -> a". - // This line essentially passes the leftmost symbol of the nested assignment ("b" in this - // example) back up to the earlier visitAssignment call for the outer assignment, which will - // create the connection "b -> a". - mNodeSets.insertIntoTopSet(leftmostSymbol); -} - -void TDependencyGraphBuilder::visitLogicalOp(TIntermBinary* intermLogicalOp) -{ - if (TIntermTyped* intermLeft = intermLogicalOp->getLeft()) { - TNodeSetPropagatingMaintainer nodeSetMaintainer(this); - - intermLeft->traverse(this); - if (TParentNodeSet* leftNodes = mNodeSets.getTopSet()) { - TGraphLogicalOp* logicalOp = mGraph->createLogicalOp(intermLogicalOp); - connectMultipleNodesToSingleNode(leftNodes, logicalOp); - } - } - - if (TIntermTyped* intermRight = intermLogicalOp->getRight()) { - TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree); - intermRight->traverse(this); - } -} - -void TDependencyGraphBuilder::visitBinaryChildren(TIntermBinary* intermBinary) -{ - if (TIntermTyped* intermLeft = intermBinary->getLeft()) - intermLeft->traverse(this); - - if (TIntermTyped* intermRight = intermBinary->getRight()) { - TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree); - intermRight->traverse(this); - } -} - -bool TDependencyGraphBuilder::visitSelection(Visit visit, TIntermSelection* intermSelection) -{ - if (TIntermNode* intermCondition = intermSelection->getCondition()) { - TNodeSetMaintainer nodeSetMaintainer(this); - - intermCondition->traverse(this); - if (TParentNodeSet* conditionNodes = mNodeSets.getTopSet()) { - TGraphSelection* selection = mGraph->createSelection(intermSelection); - connectMultipleNodesToSingleNode(conditionNodes, selection); - } - } - - if (TIntermNode* intermTrueBlock = intermSelection->getTrueBlock()) - intermTrueBlock->traverse(this); - - if (TIntermNode* intermFalseBlock = intermSelection->getFalseBlock()) - intermFalseBlock->traverse(this); - - return false; -} - -bool TDependencyGraphBuilder::visitLoop(Visit visit, TIntermLoop* intermLoop) -{ - if (TIntermTyped* intermCondition = intermLoop->getCondition()) { - TNodeSetMaintainer nodeSetMaintainer(this); - - intermCondition->traverse(this); - if (TParentNodeSet* conditionNodes = mNodeSets.getTopSet()) { - TGraphLoop* loop = mGraph->createLoop(intermLoop); - connectMultipleNodesToSingleNode(conditionNodes, loop); - } - } - - if (TIntermNode* intermBody = intermLoop->getBody()) - intermBody->traverse(this); - - if (TIntermTyped* intermExpression = intermLoop->getExpression()) - intermExpression->traverse(this); - - return false; -} - - -void TDependencyGraphBuilder::connectMultipleNodesToSingleNode(TParentNodeSet* nodes, - TGraphNode* node) const -{ - for (TParentNodeSet::const_iterator iter = nodes->begin(); iter != nodes->end(); ++iter) - { - TGraphParentNode* currentNode = *iter; - currentNode->addDependentNode(node); - } -} diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.h b/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.h deleted file mode 100644 index c5f232cb21..0000000000 --- a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.h +++ /dev/null @@ -1,181 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H -#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H - -#include "compiler/depgraph/DependencyGraph.h" - -// -// Creates a dependency graph of symbols, function calls, conditions etc. by traversing a -// intermediate tree. -// -class TDependencyGraphBuilder : public TIntermTraverser { -public: - static void build(TIntermNode* node, TDependencyGraph* graph); - - virtual void visitSymbol(TIntermSymbol*); - virtual bool visitBinary(Visit visit, TIntermBinary*); - virtual bool visitSelection(Visit visit, TIntermSelection*); - virtual bool visitAggregate(Visit visit, TIntermAggregate*); - virtual bool visitLoop(Visit visit, TIntermLoop*); - -private: - typedef std::stack TSymbolStack; - typedef std::set TParentNodeSet; - - // - // For collecting the dependent nodes of assignments, conditions, etc. - // while traversing the intermediate tree. - // - // This data structure is stack of sets. Each set contains dependency graph parent nodes. - // - class TNodeSetStack { - public: - TNodeSetStack() {}; - ~TNodeSetStack() { clear(); } - - // This should only be called after a pushSet. - // Returns NULL if the top set is empty. - TParentNodeSet* getTopSet() const - { - ASSERT(!nodeSets.empty()); - TParentNodeSet* topSet = nodeSets.top(); - return !topSet->empty() ? topSet : NULL; - } - - void pushSet() { nodeSets.push(new TParentNodeSet()); } - void popSet() - { - ASSERT(!nodeSets.empty()); - delete nodeSets.top(); - nodeSets.pop(); - } - - // Pops the top set and adds its contents to the new top set. - // This should only be called after a pushSet. - // If there is no set below the top set, the top set is just deleted. - void popSetIntoNext() - { - ASSERT(!nodeSets.empty()); - TParentNodeSet* oldTopSet = nodeSets.top(); - nodeSets.pop(); - - if (!nodeSets.empty()) { - TParentNodeSet* newTopSet = nodeSets.top(); - newTopSet->insert(oldTopSet->begin(), oldTopSet->end()); - } - - delete oldTopSet; - } - - // Does nothing if there is no top set. - // This can be called when there is no top set if we are visiting - // symbols that are not under an assignment or condition. - // We don't need to track those symbols. - void insertIntoTopSet(TGraphParentNode* node) - { - if (nodeSets.empty()) - return; - - nodeSets.top()->insert(node); - } - - void clear() - { - while (!nodeSets.empty()) - popSet(); - } - - private: - typedef std::stack TParentNodeSetStack; - - TParentNodeSetStack nodeSets; - }; - - // - // An instance of this class pushes a new node set when instantiated. - // When the instance goes out of scope, it and pops the node set. - // - class TNodeSetMaintainer { - public: - TNodeSetMaintainer(TDependencyGraphBuilder* factory) - : sets(factory->mNodeSets) { sets.pushSet(); } - ~TNodeSetMaintainer() { sets.popSet(); } - protected: - TNodeSetStack& sets; - }; - - // - // An instance of this class pushes a new node set when instantiated. - // When the instance goes out of scope, it and pops the top node set and adds its contents to - // the new top node set. - // - class TNodeSetPropagatingMaintainer { - public: - TNodeSetPropagatingMaintainer(TDependencyGraphBuilder* factory) - : sets(factory->mNodeSets) { sets.pushSet(); } - ~TNodeSetPropagatingMaintainer() { sets.popSetIntoNext(); } - protected: - TNodeSetStack& sets; - }; - - // - // An instance of this class keeps track of the leftmost symbol while we're exploring an - // assignment. - // It will push the placeholder symbol kLeftSubtree when instantiated under a left subtree, - // and kRightSubtree under a right subtree. - // When it goes out of scope, it will pop the leftmost symbol at the top of the scope. - // During traversal, the TDependencyGraphBuilder will replace kLeftSubtree with a real symbol. - // kRightSubtree will never be replaced by a real symbol because we are tracking the leftmost - // symbol. - // - class TLeftmostSymbolMaintainer { - public: - TLeftmostSymbolMaintainer(TDependencyGraphBuilder* factory, TGraphSymbol& subtree) - : leftmostSymbols(factory->mLeftmostSymbols) - { - needsPlaceholderSymbol = leftmostSymbols.empty() || leftmostSymbols.top() != &subtree; - if (needsPlaceholderSymbol) - leftmostSymbols.push(&subtree); - } - - ~TLeftmostSymbolMaintainer() - { - if (needsPlaceholderSymbol) - leftmostSymbols.pop(); - } - - protected: - TSymbolStack& leftmostSymbols; - bool needsPlaceholderSymbol; - }; - - TDependencyGraphBuilder(TDependencyGraph* graph) - : TIntermTraverser(true, false, false) - , mLeftSubtree(NULL) - , mRightSubtree(NULL) - , mGraph(graph) {} - void build(TIntermNode* intermNode) { intermNode->traverse(this); } - - void connectMultipleNodesToSingleNode(TParentNodeSet* nodes, TGraphNode* node) const; - - void visitAssignment(TIntermBinary*); - void visitLogicalOp(TIntermBinary*); - void visitBinaryChildren(TIntermBinary*); - void visitFunctionDefinition(TIntermAggregate*); - void visitFunctionCall(TIntermAggregate* intermFunctionCall); - void visitAggregateChildren(TIntermAggregate*); - - TGraphSymbol mLeftSubtree; - TGraphSymbol mRightSubtree; - - TDependencyGraph* mGraph; - TNodeSetStack mNodeSets; - TSymbolStack mLeftmostSymbols; -}; - -#endif // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.cpp b/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.cpp deleted file mode 100644 index 6fc489e7b6..0000000000 --- a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/depgraph/DependencyGraphOutput.h" - -void TDependencyGraphOutput::outputIndentation() -{ - for (int i = 0; i < getDepth(); ++i) - mSink << " "; -} - -void TDependencyGraphOutput::visitArgument(TGraphArgument* parameter) -{ - outputIndentation(); - mSink << "argument " << parameter->getArgumentNumber() << " of call to " - << parameter->getIntermFunctionCall()->getName() << "\n"; -} - -void TDependencyGraphOutput::visitFunctionCall(TGraphFunctionCall* functionCall) -{ - outputIndentation(); - mSink << "function call " << functionCall->getIntermFunctionCall()->getName() << "\n"; -} - -void TDependencyGraphOutput::visitSymbol(TGraphSymbol* symbol) -{ - outputIndentation(); - mSink << symbol->getIntermSymbol()->getSymbol() << " (symbol id: " - << symbol->getIntermSymbol()->getId() << ")\n"; -} - -void TDependencyGraphOutput::visitSelection(TGraphSelection* selection) -{ - outputIndentation(); - mSink << "selection\n"; -} - -void TDependencyGraphOutput::visitLoop(TGraphLoop* loop) -{ - outputIndentation(); - mSink << "loop condition\n"; -} - -void TDependencyGraphOutput::visitLogicalOp(TGraphLogicalOp* logicalOp) -{ - outputIndentation(); - mSink << "logical " << logicalOp->getOpString() << "\n"; -} - -void TDependencyGraphOutput::outputAllSpanningTrees(TDependencyGraph& graph) -{ - mSink << "\n"; - - for (TGraphNodeVector::const_iterator iter = graph.begin(); iter != graph.end(); ++iter) - { - TGraphNode* symbol = *iter; - mSink << "--- Dependency graph spanning tree ---\n"; - clearVisited(); - symbol->traverse(this); - mSink << "\n"; - } -} diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.h b/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.h deleted file mode 100644 index 01447da987..0000000000 --- a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H -#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H - -#include "compiler/depgraph/DependencyGraph.h" -#include "compiler/InfoSink.h" - -class TDependencyGraphOutput : public TDependencyGraphTraverser { -public: - TDependencyGraphOutput(TInfoSinkBase& sink) : mSink(sink) {} - virtual void visitSymbol(TGraphSymbol* symbol); - virtual void visitArgument(TGraphArgument* parameter); - virtual void visitFunctionCall(TGraphFunctionCall* functionCall); - virtual void visitSelection(TGraphSelection* selection); - virtual void visitLoop(TGraphLoop* loop); - virtual void visitLogicalOp(TGraphLogicalOp* logicalOp); - - void outputAllSpanningTrees(TDependencyGraph& graph); -private: - void outputIndentation(); - - TInfoSinkBase& mSink; -}; - -#endif // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphTraverse.cpp b/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphTraverse.cpp deleted file mode 100644 index b158575cec..0000000000 --- a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphTraverse.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/depgraph/DependencyGraph.h" - -// These methods do a breadth-first traversal through the graph and mark visited nodes. - -void TGraphNode::traverse(TDependencyGraphTraverser* graphTraverser) -{ - graphTraverser->markVisited(this); -} - -void TGraphParentNode::traverse(TDependencyGraphTraverser* graphTraverser) -{ - TGraphNode::traverse(graphTraverser); - - graphTraverser->incrementDepth(); - - // Visit the parent node's children. - for (TGraphNodeSet::const_iterator iter = mDependentNodes.begin(); - iter != mDependentNodes.end(); - ++iter) - { - TGraphNode* node = *iter; - if (!graphTraverser->isVisited(node)) - node->traverse(graphTraverser); - } - - graphTraverser->decrementDepth(); -} - -void TGraphArgument::traverse(TDependencyGraphTraverser* graphTraverser) -{ - graphTraverser->visitArgument(this); - TGraphParentNode::traverse(graphTraverser); -} - -void TGraphFunctionCall::traverse(TDependencyGraphTraverser* graphTraverser) -{ - graphTraverser->visitFunctionCall(this); - TGraphParentNode::traverse(graphTraverser); -} - -void TGraphSymbol::traverse(TDependencyGraphTraverser* graphTraverser) -{ - graphTraverser->visitSymbol(this); - TGraphParentNode::traverse(graphTraverser); -} - -void TGraphSelection::traverse(TDependencyGraphTraverser* graphTraverser) -{ - graphTraverser->visitSelection(this); - TGraphNode::traverse(graphTraverser); -} - -void TGraphLoop::traverse(TDependencyGraphTraverser* graphTraverser) -{ - graphTraverser->visitLoop(this); - TGraphNode::traverse(graphTraverser); -} - -void TGraphLogicalOp::traverse(TDependencyGraphTraverser* graphTraverser) -{ - graphTraverser->visitLogicalOp(this); - TGraphNode::traverse(graphTraverser); -} diff --git a/src/3rdparty/angle/src/compiler/glslang.h b/src/3rdparty/angle/src/compiler/glslang.h deleted file mode 100644 index f221199093..0000000000 --- a/src/3rdparty/angle/src/compiler/glslang.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -struct TParseContext; -extern int glslang_initialize(TParseContext* context); -extern int glslang_finalize(TParseContext* context); - -extern int glslang_scan(size_t count, - const char* const string[], - const int length[], - TParseContext* context); -extern int glslang_parse(TParseContext* context); - diff --git a/src/3rdparty/angle/src/compiler/glslang.l b/src/3rdparty/angle/src/compiler/glslang.l deleted file mode 100644 index 60663f9a6b..0000000000 --- a/src/3rdparty/angle/src/compiler/glslang.l +++ /dev/null @@ -1,355 +0,0 @@ -/* -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -This file contains the Lex specification for GLSL ES. -Based on ANSI C grammar, Lex specification: -http://www.lysator.liu.se/c/ANSI-C-grammar-l.html - -IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh, -WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). -*/ - -%top{ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// This file is auto-generated by generate_parser.sh. DO NOT EDIT! - -// Ignore errors in auto-generated code. -#if defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wswitch-enum" -#elif defined(_MSC_VER) -#pragma warning(disable: 4065) -#pragma warning(disable: 4189) -#pragma warning(disable: 4505) -#pragma warning(disable: 4701) -#endif -} - -%{ -#include "compiler/glslang.h" -#include "compiler/ParseHelper.h" -#include "compiler/preprocessor/Token.h" -#include "compiler/util.h" -#include "glslang_tab.h" - -/* windows only pragma */ -#ifdef _MSC_VER -#pragma warning(disable : 4102) -#endif - -#define YY_USER_ACTION \ - yylloc->first_file = yylloc->last_file = yycolumn; \ - yylloc->first_line = yylloc->last_line = yylineno; - -#define YY_INPUT(buf, result, max_size) \ - result = string_input(buf, max_size, yyscanner); - -static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner); -static int check_type(yyscan_t yyscanner); -static int reserved_word(yyscan_t yyscanner); -static int int_constant(yyscan_t yyscanner); -static int float_constant(yyscan_t yyscanner); -%} - -%option noyywrap nounput never-interactive -%option yylineno reentrant bison-bridge bison-locations -%option extra-type="TParseContext*" - -D [0-9] -L [a-zA-Z_] -H [a-fA-F0-9] -E [Ee][+-]?{D}+ -O [0-7] - -%% - -"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" { return FLOAT_TYPE; } -"int" { return INT_TYPE; } -"void" { return VOID_TYPE; } -"bool" { return BOOL_TYPE; } -"true" { yylval->lex.b = true; return BOOLCONSTANT; } -"false" { yylval->lex.b = false; return BOOLCONSTANT; } - -"discard" { return DISCARD; } -"return" { return RETURN; } - -"mat2" { return MATRIX2; } -"mat3" { return MATRIX3; } -"mat4" { return MATRIX4; } - -"vec2" { return VEC2; } -"vec3" { return VEC3; } -"vec4" { return VEC4; } -"ivec2" { return IVEC2; } -"ivec3" { return IVEC3; } -"ivec4" { return IVEC4; } -"bvec2" { return BVEC2; } -"bvec3" { return BVEC3; } -"bvec4" { return BVEC4; } - -"sampler2D" { return SAMPLER2D; } -"samplerCube" { return SAMPLERCUBE; } -"samplerExternalOES" { return SAMPLER_EXTERNAL_OES; } -"sampler2DRect" { return SAMPLER2DRECT; } - -"struct" { return STRUCT; } - -"asm" { return reserved_word(yyscanner); } - -"class" { return reserved_word(yyscanner); } -"union" { return reserved_word(yyscanner); } -"enum" { return reserved_word(yyscanner); } -"typedef" { return reserved_word(yyscanner); } -"template" { return reserved_word(yyscanner); } -"this" { return reserved_word(yyscanner); } -"packed" { return reserved_word(yyscanner); } - -"goto" { return reserved_word(yyscanner); } -"switch" { return reserved_word(yyscanner); } -"default" { return reserved_word(yyscanner); } - -"inline" { return reserved_word(yyscanner); } -"noinline" { return reserved_word(yyscanner); } -"volatile" { return reserved_word(yyscanner); } -"public" { return reserved_word(yyscanner); } -"static" { return reserved_word(yyscanner); } -"extern" { return reserved_word(yyscanner); } -"external" { return reserved_word(yyscanner); } -"interface" { return reserved_word(yyscanner); } -"flat" { return reserved_word(yyscanner); } - -"long" { return reserved_word(yyscanner); } -"short" { return reserved_word(yyscanner); } -"double" { return reserved_word(yyscanner); } -"half" { return reserved_word(yyscanner); } -"fixed" { return reserved_word(yyscanner); } -"unsigned" { return reserved_word(yyscanner); } -"superp" { return reserved_word(yyscanner); } - -"input" { return reserved_word(yyscanner); } -"output" { return reserved_word(yyscanner); } - -"hvec2" { return reserved_word(yyscanner); } -"hvec3" { return reserved_word(yyscanner); } -"hvec4" { return reserved_word(yyscanner); } -"dvec2" { return reserved_word(yyscanner); } -"dvec3" { return reserved_word(yyscanner); } -"dvec4" { return reserved_word(yyscanner); } -"fvec2" { return reserved_word(yyscanner); } -"fvec3" { return reserved_word(yyscanner); } -"fvec4" { return reserved_word(yyscanner); } - -"sampler1D" { return reserved_word(yyscanner); } -"sampler3D" { return reserved_word(yyscanner); } -"sampler1DShadow" { return reserved_word(yyscanner); } -"sampler2DShadow" { return reserved_word(yyscanner); } -"sampler3DRect" { return reserved_word(yyscanner); } -"sampler2DRectShadow" { return reserved_word(yyscanner); } - -"sizeof" { return reserved_word(yyscanner); } -"cast" { return reserved_word(yyscanner); } - -"namespace" { return reserved_word(yyscanner); } -"using" { return reserved_word(yyscanner); } - -{L}({L}|{D})* { - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); -} - -0[xX]{H}+ { return int_constant(yyscanner); } -0{O}+ { return int_constant(yyscanner); } -{D}+ { return int_constant(yyscanner); } - -{D}+{E} { return float_constant(yyscanner); } -{D}+"."{D}*({E})? { return float_constant(yyscanner); } -"."{D}+({E})? { return float_constant(yyscanner); } - -"+=" { 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; } -";" { return SEMICOLON; } -("{"|"<%") { return LEFT_BRACE; } -("}"|"%>") { return RIGHT_BRACE; } -"," { return COMMA; } -":" { return COLON; } -"=" { return EQUAL; } -"(" { return LEFT_PAREN; } -")" { return RIGHT_PAREN; } -("["|"<:") { return LEFT_BRACKET; } -("]"|":>") { return RIGHT_BRACKET; } -"." { return DOT; } -"!" { return BANG; } -"-" { return DASH; } -"~" { return TILDE; } -"+" { return PLUS; } -"*" { return STAR; } -"/" { return SLASH; } -"%" { return PERCENT; } -"<" { return LEFT_ANGLE; } -">" { return RIGHT_ANGLE; } -"|" { return VERTICAL_BAR; } -"^" { return CARET; } -"&" { return AMPERSAND; } -"?" { return QUESTION; } - -[ \t\v\n\f\r] { } -<> { yyterminate(); } -. { assert(false); return 0; } - -%% - -yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) { - pp::Token token; - yyget_extra(yyscanner)->preprocessor.lex(&token); - yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size(); - if (len < max_size) - memcpy(buf, token.text.c_str(), len); - yyset_column(token.location.file, yyscanner); - yyset_lineno(token.location.line, yyscanner); - - if (len >= max_size) - YY_FATAL_ERROR("Input buffer overflow"); - else if (len > 0) - buf[len++] = ' '; - return len; -} - -int check_type(yyscan_t yyscanner) { - struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; - - int token = IDENTIFIER; - TSymbol* symbol = yyextra->symbolTable.find(yytext); - if (symbol && symbol->isVariable()) { - TVariable* variable = static_cast(symbol); - if (variable->isUserType()) - 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(*yylloc, "Illegal use of reserved word", yytext, ""); - yyextra->recover(); - return 0; -} - -void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) { - context->error(*lloc, reason, yyget_text(context->scanner)); - context->recover(); -} - -int int_constant(yyscan_t yyscanner) { - struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; - - if (!atoi_clamp(yytext, &(yylval->lex.i))) - yyextra->warning(*yylloc, "Integer overflow", yytext, ""); - return INTCONSTANT; -} - -int float_constant(yyscan_t yyscanner) { - struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; - - if (!atof_clamp(yytext, &(yylval->lex.f))) - yyextra->warning(*yylloc, "Float overflow", yytext, ""); - return FLOATCONSTANT; -} - -int glslang_initialize(TParseContext* context) { - yyscan_t scanner = NULL; - if (yylex_init_extra(context, &scanner)) - return 1; - - context->scanner = scanner; - return 0; -} - -int glslang_finalize(TParseContext* context) { - yyscan_t scanner = context->scanner; - if (scanner == NULL) return 0; - - context->scanner = NULL; - yylex_destroy(scanner); - - return 0; -} - -int glslang_scan(size_t count, const char* const string[], const int length[], - TParseContext* context) { - yyrestart(NULL, context->scanner); - yyset_column(0, context->scanner); - yyset_lineno(1, context->scanner); - - // Initialize preprocessor. - if (!context->preprocessor.init(count, string, length)) - return 1; - context->preprocessor.setMaxTokenLength(SH_MAX_TOKEN_LENGTH); - - // Define extension macros. - const TExtensionBehavior& extBehavior = context->extensionBehavior(); - for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); - iter != extBehavior.end(); ++iter) { - context->preprocessor.predefineMacro(iter->first.c_str(), 1); - } - if (context->fragmentPrecisionHigh) - context->preprocessor.predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1); - - return 0; -} - diff --git a/src/3rdparty/angle/src/compiler/glslang.y b/src/3rdparty/angle/src/compiler/glslang.y deleted file mode 100644 index c64f736f41..0000000000 --- a/src/3rdparty/angle/src/compiler/glslang.y +++ /dev/null @@ -1,2002 +0,0 @@ -/* -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -This file contains the Yacc grammar for GLSL ES. -Based on ANSI C Yacc grammar: -http://www.lysator.liu.se/c/ANSI-C-grammar-y.html - -IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh, -WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). -*/ - -%{ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// This file is auto-generated by generate_parser.sh. DO NOT EDIT! - -// Ignore errors in auto-generated code. -#if defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wswitch-enum" -#elif defined(_MSC_VER) -#pragma warning(disable: 4065) -#pragma warning(disable: 4189) -#pragma warning(disable: 4505) -#pragma warning(disable: 4701) -#endif - -#include "compiler/SymbolTable.h" -#include "compiler/ParseHelper.h" -#include "GLSLANG/ShaderLang.h" - -#define YYENABLE_NLS 0 - -#define YYLEX_PARAM context->scanner -%} - -%expect 1 /* One shift reduce conflict because of if | else */ -%pure-parser -%parse-param {TParseContext* context} -%locations - -%code requires { -#define YYLTYPE TSourceLoc -#define YYLTYPE_IS_DECLARED 1 -#define SH_MAX_TOKEN_LENGTH 256 // WebGL spec. -} - -%union { - struct { - union { - TString *string; - float f; - int i; - bool b; - }; - TSymbol* symbol; - } lex; - struct { - TOperator op; - union { - TIntermNode* intermNode; - TIntermNodePair nodePair; - TIntermTyped* intermTypedNode; - TIntermAggregate* intermAggregate; - }; - union { - TPublicType type; - TPrecision precision; - TQualifier qualifier; - TFunction* function; - TParameter param; - TField* field; - TFieldList* fieldList; - }; - } interm; -} - -%{ -extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner); -extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason); - -#define YYLLOC_DEFAULT(Current, Rhs, N) \ - do { \ - if (YYID(N)) { \ - (Current).first_file = YYRHSLOC(Rhs, 1).first_file; \ - (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ - (Current).last_file = YYRHSLOC(Rhs, N).last_file; \ - (Current).last_line = YYRHSLOC(Rhs, N).last_line; \ - } \ - else { \ - (Current).first_file = YYRHSLOC(Rhs, 0).last_file; \ - (Current).first_line = YYRHSLOC(Rhs, 0).last_line; \ - (Current).last_file = YYRHSLOC(Rhs, 0).last_file; \ - (Current).last_line = YYRHSLOC(Rhs, 0).last_line; \ - } \ - } while (0) - -#define VERTEX_ONLY(S, L) { \ - if (context->shaderType != SH_VERTEX_SHADER) { \ - context->error(L, " supported in vertex shaders only ", S); \ - context->recover(); \ - } \ -} - -#define FRAG_ONLY(S, L) { \ - if (context->shaderType != SH_FRAGMENT_SHADER) { \ - context->error(L, " supported in fragment shaders only ", S); \ - context->recover(); \ - } \ -} -%} - -%token 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 -%token BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4 -%token MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING -%token STRUCT VOID_TYPE WHILE -%token SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT - -%token IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT -%token LEFT_OP RIGHT_OP -%token INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP -%token AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN -%token MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN -%token SUB_ASSIGN - -%token LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT -%token COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT -%token LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION - -%type identifier -%type assignment_operator unary_operator -%type variable_identifier primary_expression postfix_expression -%type expression integer_expression assignment_expression -%type unary_expression multiplicative_expression additive_expression -%type relational_expression equality_expression -%type conditional_expression constant_expression -%type logical_or_expression logical_xor_expression logical_and_expression -%type shift_expression and_expression exclusive_or_expression inclusive_or_expression -%type function_call initializer condition conditionopt - -%type translation_unit function_definition -%type statement simple_statement -%type statement_list compound_statement -%type declaration_statement selection_statement expression_statement -%type declaration external_declaration -%type for_init_statement compound_statement_no_new_scope -%type selection_rest_statement for_rest_statement -%type iteration_statement jump_statement statement_no_new_scope statement_with_scope -%type single_declaration init_declarator_list - -%type parameter_declaration parameter_declarator parameter_type_specifier -%type parameter_qualifier - -%type precision_qualifier -%type type_qualifier fully_specified_type type_specifier -%type type_specifier_no_prec type_specifier_nonarray -%type struct_specifier -%type struct_declarator -%type struct_declarator_list struct_declaration struct_declaration_list -%type function_header function_declarator function_identifier -%type function_header_with_parameters function_call_header -%type function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype -%type function_call_or_method - -%start translation_unit -%% - -identifier - : IDENTIFIER - | TYPE_NAME - -variable_identifier - : IDENTIFIER { - // The symbol table search was done in the lexical phase - const TSymbol* symbol = $1.symbol; - const TVariable* variable; - if (symbol == 0) { - context->error(@1, "undeclared identifier", $1.string->c_str()); - context->recover(); - TType type(EbtFloat, EbpUndefined); - TVariable* fakeVariable = new TVariable($1.string, type); - context->symbolTable.insert(*fakeVariable); - variable = fakeVariable; - } else { - // This identifier can only be a variable type symbol - if (! symbol->isVariable()) { - context->error(@1, "variable expected", $1.string->c_str()); - context->recover(); - } - - variable = static_cast(symbol); - - if (context->symbolTable.findBuiltIn(variable->getName()) && - !variable->getExtension().empty() && - context->extensionErrorCheck(@1, variable->getExtension())) { - context->recover(); - } - } - - // don't delete $1.string, it's used by error recovery, and the pool - // pop will reclaim the memory - - if (variable->getType().getQualifier() == EvqConst ) { - ConstantUnion* constArray = variable->getConstPointer(); - TType t(variable->getType()); - $$ = context->intermediate.addConstantUnion(constArray, t, @1); - } else - $$ = context->intermediate.addSymbol(variable->getUniqueId(), - variable->getName(), - variable->getType(), - @1); - } - ; - -primary_expression - : variable_identifier { - $$ = $1; - } - | INTCONSTANT { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setIConst($1.i); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @1); - } - | FLOATCONSTANT { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setFConst($1.f); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1); - } - | BOOLCONSTANT { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst($1.b); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @1); - } - | LEFT_PAREN expression RIGHT_PAREN { - $$ = $2; - } - ; - -postfix_expression - : primary_expression { - $$ = $1; - } - | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET { - $$ = context->addIndexExpression($1, @2, $3); - } - | function_call { - $$ = $1; - } - | postfix_expression DOT identifier { - if ($1->isArray()) { - context->error(@3, "cannot apply dot operator to an array", "."); - context->recover(); - } - - if ($1->isVector()) { - TVectorFields fields; - if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, @3)) { - fields.num = 1; - fields.offsets[0] = 0; - context->recover(); - } - - if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields - $$ = context->addConstVectorNode(fields, $1, @3); - if ($$ == 0) { - context->recover(); - $$ = $1; - } - else - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size())); - } else { - TString vectorString = *$3.string; - TIntermTyped* index = context->intermediate.addSwizzle(fields, @3); - $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, @2); - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size())); - } - } else if ($1->isMatrix()) { - TMatrixFields fields; - if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, @3)) { - fields.wholeRow = false; - fields.wholeCol = false; - fields.row = 0; - fields.col = 0; - context->recover(); - } - - if (fields.wholeRow || fields.wholeCol) { - context->error(@2, " non-scalar fields not implemented yet", "."); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setIConst(0); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3); - $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2); - $$->setType(TType($1->getBasicType(), $1->getPrecision(),EvqTemporary, $1->getNominalSize())); - } else { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3); - $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2); - $$->setType(TType($1->getBasicType(), $1->getPrecision())); - } - } else if ($1->getBasicType() == EbtStruct) { - bool fieldFound = false; - const TFieldList& fields = $1->getType().getStruct()->fields(); - unsigned int i; - for (i = 0; i < fields.size(); ++i) { - if (fields[i]->name() == *$3.string) { - fieldFound = true; - break; - } - } - if (fieldFound) { - if ($1->getType().getQualifier() == EvqConst) { - $$ = context->addConstStruct(*$3.string, $1, @2); - if ($$ == 0) { - context->recover(); - $$ = $1; - } - else { - $$->setType(*fields[i]->type()); - // change the qualifier of the return type, not of the structure field - // as the structure definition is shared between various structures. - $$->getTypePointer()->setQualifier(EvqConst); - } - } else { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setIConst(i); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *fields[i]->type(), @3); - $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, @2); - $$->setType(*fields[i]->type()); - } - } else { - context->error(@2, " no such field in structure", $3.string->c_str()); - context->recover(); - $$ = $1; - } - } else { - context->error(@2, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str()); - context->recover(); - $$ = $1; - } - // don't delete $3.string, it's from the pool - } - | postfix_expression INC_OP { - if (context->lValueErrorCheck(@2, "++", $1)) - context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, @2, context->symbolTable); - if ($$ == 0) { - context->unaryOpError(@2, "++", $1->getCompleteString()); - context->recover(); - $$ = $1; - } - } - | postfix_expression DEC_OP { - if (context->lValueErrorCheck(@2, "--", $1)) - context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, @2, context->symbolTable); - if ($$ == 0) { - context->unaryOpError(@2, "--", $1->getCompleteString()); - context->recover(); - $$ = $1; - } - } - ; - -integer_expression - : expression { - if (context->integerErrorCheck($1, "[]")) - context->recover(); - $$ = $1; - } - ; - -function_call - : function_call_or_method { - TFunction* fnCall = $1.function; - TOperator op = fnCall->getBuiltInOp(); - - if (op != EOpNull) - { - // - // Then this should be a constructor. - // Don't go through the symbol table for constructors. - // Their parameters will be verified algorithmically. - // - TType type(EbtVoid, EbpUndefined); // use this to get the type back - if (context->constructorErrorCheck(@1, $1.intermNode, *fnCall, op, &type)) { - $$ = 0; - } else { - // - // It's a constructor, of type 'type'. - // - $$ = context->addConstructor($1.intermNode, &type, op, fnCall, @1); - } - - if ($$ == 0) { - context->recover(); - $$ = context->intermediate.setAggregateOperator(0, op, @1); - } - $$->setType(type); - } else { - // - // Not a constructor. Find it in the symbol table. - // - const TFunction* fnCandidate; - bool builtIn; - fnCandidate = context->findFunction(@1, fnCall, &builtIn); - if (fnCandidate) { - // - // A declared function. - // - if (builtIn && !fnCandidate->getExtension().empty() && - context->extensionErrorCheck(@1, fnCandidate->getExtension())) { - context->recover(); - } - op = fnCandidate->getBuiltInOp(); - if (builtIn && op != EOpNull) { - // - // A function call mapped to a built-in operation. - // - if (fnCandidate->getParamCount() == 1) { - // - // Treat it like a built-in unary operator. - // - $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1, context->symbolTable); - if ($$ == 0) { - std::stringstream extraInfoStream; - extraInfoStream << "built in unary operator function. Type: " << static_cast($1.intermNode)->getCompleteString(); - std::string extraInfo = extraInfoStream.str(); - context->error($1.intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str()); - YYERROR; - } - } else { - $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1); - } - } else { - // This is a real function call - - $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1); - $$->setType(fnCandidate->getReturnType()); - - // this is how we know whether the given function is a builtIn function or a user defined function - // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also - // if builtIn == true, it's definitely a builtIn function with EOpNull - if (!builtIn) - $$->getAsAggregate()->setUserDefined(); - $$->getAsAggregate()->setName(fnCandidate->getMangledName()); - - TQualifier qual; - for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) { - qual = fnCandidate->getParam(i).type->getQualifier(); - if (qual == EvqOut || qual == EvqInOut) { - if (context->lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) { - context->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error"); - context->recover(); - } - } - } - } - $$->setType(fnCandidate->getReturnType()); - } else { - // error message was put out by PaFindFunction() - // Put on a dummy node for error recovery - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setFConst(0.0f); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1); - context->recover(); - } - } - delete fnCall; - } - ; - -function_call_or_method - : function_call_generic { - $$ = $1; - } - | postfix_expression DOT function_call_generic { - context->error(@3, "methods are not supported", ""); - context->recover(); - $$ = $3; - } - ; - -function_call_generic - : function_call_header_with_parameters RIGHT_PAREN { - $$ = $1; - } - | function_call_header_no_parameters RIGHT_PAREN { - $$ = $1; - } - ; - -function_call_header_no_parameters - : function_call_header VOID_TYPE { - $$.function = $1; - $$.intermNode = 0; - } - | function_call_header { - $$.function = $1; - $$.intermNode = 0; - } - ; - -function_call_header_with_parameters - : function_call_header assignment_expression { - TParameter param = { 0, new TType($2->getType()) }; - $1->addParameter(param); - $$.function = $1; - $$.intermNode = $2; - } - | function_call_header_with_parameters COMMA assignment_expression { - TParameter param = { 0, new TType($3->getType()) }; - $1.function->addParameter(param); - $$.function = $1.function; - $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, @2); - } - ; - -function_call_header - : function_identifier LEFT_PAREN { - $$ = $1; - } - ; - -// Grammar Note: Constructors look like functions, but are recognized as types. - -function_identifier - : type_specifier_nonarray { - // - // Constructor - // - TOperator op = EOpNull; - if ($1.userDef) { - op = EOpConstructStruct; - } else { - switch ($1.type) { - case EbtFloat: - if ($1.matrix) { - switch($1.size) { - case 2: op = EOpConstructMat2; break; - case 3: op = EOpConstructMat3; break; - case 4: op = EOpConstructMat4; break; - } - } else { - switch($1.size) { - case 1: op = EOpConstructFloat; break; - case 2: op = EOpConstructVec2; break; - case 3: op = EOpConstructVec3; break; - case 4: op = EOpConstructVec4; break; - } - } - break; - case EbtInt: - switch($1.size) { - case 1: op = EOpConstructInt; break; - case 2: op = EOpConstructIVec2; break; - case 3: op = EOpConstructIVec3; break; - case 4: op = EOpConstructIVec4; break; - } - break; - case EbtBool: - switch($1.size) { - case 1: op = EOpConstructBool; break; - case 2: op = EOpConstructBVec2; break; - case 3: op = EOpConstructBVec3; break; - case 4: op = EOpConstructBVec4; break; - } - break; - default: break; - } - if (op == EOpNull) { - context->error(@1, "cannot construct this type", getBasicString($1.type)); - context->recover(); - $1.type = EbtFloat; - op = EOpConstructFloat; - } - } - TString tempString; - TType type($1); - TFunction *function = new TFunction(&tempString, type, op); - $$ = function; - } - | IDENTIFIER { - if (context->reservedErrorCheck(@1, *$1.string)) - context->recover(); - TType type(EbtVoid, EbpUndefined); - TFunction *function = new TFunction($1.string, type); - $$ = function; - } - ; - -unary_expression - : postfix_expression { - $$ = $1; - } - | INC_OP unary_expression { - if (context->lValueErrorCheck(@1, "++", $2)) - context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, @1, context->symbolTable); - if ($$ == 0) { - context->unaryOpError(@1, "++", $2->getCompleteString()); - context->recover(); - $$ = $2; - } - } - | DEC_OP unary_expression { - if (context->lValueErrorCheck(@1, "--", $2)) - context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, @1, context->symbolTable); - if ($$ == 0) { - context->unaryOpError(@1, "--", $2->getCompleteString()); - context->recover(); - $$ = $2; - } - } - | unary_operator unary_expression { - if ($1.op != EOpNull) { - $$ = context->intermediate.addUnaryMath($1.op, $2, @1, context->symbolTable); - if ($$ == 0) { - const char* errorOp = ""; - switch($1.op) { - case EOpNegative: errorOp = "-"; break; - case EOpLogicalNot: errorOp = "!"; break; - default: break; - } - context->unaryOpError(@1, errorOp, $2->getCompleteString()); - context->recover(); - $$ = $2; - } - } else - $$ = $2; - } - ; -// Grammar Note: No traditional style type casts. - -unary_operator - : PLUS { $$.op = EOpNull; } - | DASH { $$.op = EOpNegative; } - | BANG { $$.op = EOpLogicalNot; } - ; -// Grammar Note: No '*' or '&' unary ops. Pointers are not supported. - -multiplicative_expression - : unary_expression { $$ = $1; } - | multiplicative_expression STAR unary_expression { - $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, @2, context->symbolTable); - if ($$ == 0) { - context->binaryOpError(@2, "*", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - $$ = $1; - } - } - | multiplicative_expression SLASH unary_expression { - $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, @2, context->symbolTable); - if ($$ == 0) { - context->binaryOpError(@2, "/", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - $$ = $1; - } - } - ; - -additive_expression - : multiplicative_expression { $$ = $1; } - | additive_expression PLUS multiplicative_expression { - $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, @2, context->symbolTable); - if ($$ == 0) { - context->binaryOpError(@2, "+", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - $$ = $1; - } - } - | additive_expression DASH multiplicative_expression { - $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, @2, context->symbolTable); - if ($$ == 0) { - context->binaryOpError(@2, "-", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - $$ = $1; - } - } - ; - -shift_expression - : additive_expression { $$ = $1; } - ; - -relational_expression - : shift_expression { $$ = $1; } - | relational_expression LEFT_ANGLE shift_expression { - $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, @2, context->symbolTable); - if ($$ == 0) { - context->binaryOpError(@2, "<", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } - } - | relational_expression RIGHT_ANGLE shift_expression { - $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, @2, context->symbolTable); - if ($$ == 0) { - context->binaryOpError(@2, ">", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } - } - | relational_expression LE_OP shift_expression { - $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, @2, context->symbolTable); - if ($$ == 0) { - context->binaryOpError(@2, "<=", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } - } - | relational_expression GE_OP shift_expression { - $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, @2, context->symbolTable); - if ($$ == 0) { - context->binaryOpError(@2, ">=", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } - } - ; - -equality_expression - : relational_expression { $$ = $1; } - | equality_expression EQ_OP relational_expression { - $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, @2, context->symbolTable); - if ($$ == 0) { - context->binaryOpError(@2, "==", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } - } - | equality_expression NE_OP relational_expression { - $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, @2, context->symbolTable); - if ($$ == 0) { - context->binaryOpError(@2, "!=", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } - } - ; - -and_expression - : equality_expression { $$ = $1; } - ; - -exclusive_or_expression - : and_expression { $$ = $1; } - ; - -inclusive_or_expression - : exclusive_or_expression { $$ = $1; } - ; - -logical_and_expression - : inclusive_or_expression { $$ = $1; } - | logical_and_expression AND_OP inclusive_or_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, @2, context->symbolTable); - if ($$ == 0) { - context->binaryOpError(@2, "&&", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } - } - ; - -logical_xor_expression - : logical_and_expression { $$ = $1; } - | logical_xor_expression XOR_OP logical_and_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, @2, context->symbolTable); - if ($$ == 0) { - context->binaryOpError(@2, "^^", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } - } - ; - -logical_or_expression - : logical_xor_expression { $$ = $1; } - | logical_or_expression OR_OP logical_xor_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, @2, context->symbolTable); - if ($$ == 0) { - context->binaryOpError(@2, "||", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } - } - ; - -conditional_expression - : logical_or_expression { $$ = $1; } - | logical_or_expression QUESTION expression COLON assignment_expression { - if (context->boolErrorCheck(@2, $1)) - context->recover(); - - $$ = context->intermediate.addSelection($1, $3, $5, @2); - if ($3->getType() != $5->getType()) - $$ = 0; - - if ($$ == 0) { - context->binaryOpError(@2, ":", $3->getCompleteString(), $5->getCompleteString()); - context->recover(); - $$ = $5; - } - } - ; - -assignment_expression - : conditional_expression { $$ = $1; } - | unary_expression assignment_operator assignment_expression { - if (context->lValueErrorCheck(@2, "assign", $1)) - context->recover(); - $$ = context->intermediate.addAssign($2.op, $1, $3, @2); - if ($$ == 0) { - context->assignError(@2, "assign", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - $$ = $1; - } - } - ; - -assignment_operator - : EQUAL { $$.op = EOpAssign; } - | MUL_ASSIGN { $$.op = EOpMulAssign; } - | DIV_ASSIGN { $$.op = EOpDivAssign; } - | ADD_ASSIGN { $$.op = EOpAddAssign; } - | SUB_ASSIGN { $$.op = EOpSubAssign; } - ; - -expression - : assignment_expression { - $$ = $1; - } - | expression COMMA assignment_expression { - $$ = context->intermediate.addComma($1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, ",", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - $$ = $3; - } - } - ; - -constant_expression - : conditional_expression { - if (context->constErrorCheck($1)) - context->recover(); - $$ = $1; - } - ; - -declaration - : function_prototype SEMICOLON { - TFunction &function = *($1.function); - - TIntermAggregate *prototype = new TIntermAggregate; - prototype->setType(function.getReturnType()); - prototype->setName(function.getName()); - - for (size_t i = 0; i < function.getParamCount(); i++) - { - const TParameter ¶m = function.getParam(i); - if (param.name != 0) - { - TVariable variable(param.name, *param.type); - - prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), @1), @1); - } - else - { - prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, @1), @1); - } - } - - prototype->setOp(EOpPrototype); - $$ = prototype; - - context->symbolTable.pop(); - } - | init_declarator_list SEMICOLON { - if ($1.intermAggregate) - $1.intermAggregate->setOp(EOpDeclaration); - $$ = $1.intermAggregate; - } - | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON { - if (($2 == EbpHigh) && (context->shaderType == SH_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) { - context->error(@1, "precision is not supported in fragment shader", "highp"); - context->recover(); - } - if (!context->symbolTable.setDefaultPrecision( $3, $2 )) { - context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.type)); - context->recover(); - } - $$ = 0; - } - ; - -function_prototype - : function_declarator RIGHT_PAREN { - // - // Multiple declarations of the same function are allowed. - // - // If this is a definition, the definition production code will check for redefinitions - // (we don't know at this point if it's a definition or not). - // - // Redeclarations are allowed. But, return types and parameter qualifiers must match. - // - TFunction* prevDec = static_cast(context->symbolTable.find($1->getMangledName())); - if (prevDec) { - if (prevDec->getReturnType() != $1->getReturnType()) { - context->error(@2, "overloaded functions must have the same return type", $1->getReturnType().getBasicString()); - context->recover(); - } - for (size_t i = 0; i < prevDec->getParamCount(); ++i) { - if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) { - context->error(@2, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString()); - context->recover(); - } - } - } - - // - // Check for previously declared variables using the same name. - // - TSymbol *prevSym = context->symbolTable.find($1->getName()); - if (prevSym) - { - if (!prevSym->isFunction()) - { - context->error(@2, "redefinition", $1->getName().c_str(), "function"); - context->recover(); - } - } - else - { - // Insert the unmangled name to detect potential future redefinition as a variable. - context->symbolTable.getOuterLevel()->insert($1->getName(), *$1); - } - - // - // If this is a redeclaration, it could also be a definition, - // in which case, we want to use the variable names from this one, and not the one that's - // being redeclared. So, pass back up this declaration, not the one in the symbol table. - // - $$.function = $1; - - // We're at the inner scope level of the function's arguments and body statement. - // Add the function prototype to the surrounding scope instead. - context->symbolTable.getOuterLevel()->insert(*$$.function); - } - ; - -function_declarator - : function_header { - $$ = $1; - } - | function_header_with_parameters { - $$ = $1; - } - ; - - -function_header_with_parameters - : function_header parameter_declaration { - // Add the parameter - $$ = $1; - if ($2.param.type->getBasicType() != EbtVoid) - $1->addParameter($2.param); - else - delete $2.param.type; - } - | function_header_with_parameters COMMA parameter_declaration { - // - // Only first parameter of one-parameter functions can be void - // The check for named parameters not being void is done in parameter_declarator - // - if ($3.param.type->getBasicType() == EbtVoid) { - // - // This parameter > first is void - // - context->error(@2, "cannot be an argument type except for '(void)'", "void"); - context->recover(); - delete $3.param.type; - } else { - // Add the parameter - $$ = $1; - $1->addParameter($3.param); - } - } - ; - -function_header - : fully_specified_type IDENTIFIER LEFT_PAREN { - if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) { - context->error(@2, "no qualifiers allowed for function return", getQualifierString($1.qualifier)); - context->recover(); - } - // make sure a sampler is not involved as well... - if (context->structQualifierErrorCheck(@2, $1)) - context->recover(); - - // Add the function as a prototype after parsing it (we do not support recursion) - TFunction *function; - TType type($1); - function = new TFunction($2.string, type); - $$ = function; - - context->symbolTable.push(); - } - ; - -parameter_declarator - // Type + name - : type_specifier identifier { - if ($1.type == EbtVoid) { - context->error(@2, "illegal use of type 'void'", $2.string->c_str()); - context->recover(); - } - if (context->reservedErrorCheck(@2, *$2.string)) - context->recover(); - TParameter param = {$2.string, new TType($1)}; - $$.param = param; - } - | type_specifier identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { - // Check that we can make an array out of this type - if (context->arrayTypeErrorCheck(@3, $1)) - context->recover(); - - if (context->reservedErrorCheck(@2, *$2.string)) - context->recover(); - - int size; - if (context->arraySizeErrorCheck(@3, $4, size)) - context->recover(); - $1.setArray(true, size); - - TType* type = new TType($1); - TParameter param = { $2.string, type }; - $$.param = param; - } - ; - -parameter_declaration - // - // The only parameter qualifier a parameter can have are - // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST. - // - - // - // Type + name - // - : type_qualifier parameter_qualifier parameter_declarator { - $$ = $3; - if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type)) - context->recover(); - } - | parameter_qualifier parameter_declarator { - $$ = $2; - if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type)) - context->recover(); - if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type)) - context->recover(); - } - // - // Only type - // - | type_qualifier parameter_qualifier parameter_type_specifier { - $$ = $3; - if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type)) - context->recover(); - } - | parameter_qualifier parameter_type_specifier { - $$ = $2; - if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type)) - context->recover(); - if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type)) - context->recover(); - } - ; - -parameter_qualifier - : /* empty */ { - $$ = EvqIn; - } - | IN_QUAL { - $$ = EvqIn; - } - | OUT_QUAL { - $$ = EvqOut; - } - | INOUT_QUAL { - $$ = EvqInOut; - } - ; - -parameter_type_specifier - : type_specifier { - TParameter param = { 0, new TType($1) }; - $$.param = param; - } - ; - -init_declarator_list - : single_declaration { - $$ = $1; - } - | init_declarator_list COMMA identifier { - if ($1.type.type == EbtInvariant && !$3.symbol) - { - context->error(@3, "undeclared identifier declared as invariant", $3.string->c_str()); - context->recover(); - } - - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), @3); - $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, @3); - - if (context->structQualifierErrorCheck(@3, $$.type)) - context->recover(); - - if (context->nonInitConstErrorCheck(@3, *$3.string, $$.type, false)) - context->recover(); - - TVariable* variable = 0; - if (context->nonInitErrorCheck(@3, *$3.string, $$.type, variable)) - context->recover(); - if (symbol && variable) - symbol->setId(variable->getUniqueId()); - } - | init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET { - if (context->structQualifierErrorCheck(@3, $1.type)) - context->recover(); - - if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true)) - context->recover(); - - $$ = $1; - - if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type)) - context->recover(); - else { - $1.type.setArray(true); - TVariable* variable; - if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable)) - context->recover(); - } - } - | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { - if (context->structQualifierErrorCheck(@3, $1.type)) - context->recover(); - - if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true)) - context->recover(); - - $$ = $1; - - if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type)) - context->recover(); - else { - int size; - if (context->arraySizeErrorCheck(@4, $5, size)) - context->recover(); - $1.type.setArray(true, size); - TVariable* variable = 0; - if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable)) - context->recover(); - TType type = TType($1.type); - type.setArraySize(size); - $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, @3), @3); - } - } - | init_declarator_list COMMA identifier EQUAL initializer { - if (context->structQualifierErrorCheck(@3, $1.type)) - context->recover(); - - $$ = $1; - - TIntermNode* intermNode; - if (!context->executeInitializer(@3, *$3.string, $1.type, $5, intermNode)) { - // - // build the intermediate representation - // - if (intermNode) - $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, @4); - else - $$.intermAggregate = $1.intermAggregate; - } else { - context->recover(); - $$.intermAggregate = 0; - } - } - ; - -single_declaration - : fully_specified_type { - $$.type = $1; - $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), @1), @1); - } - | fully_specified_type identifier { - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); - - if (context->structQualifierErrorCheck(@2, $$.type)) - context->recover(); - - if (context->nonInitConstErrorCheck(@2, *$2.string, $$.type, false)) - context->recover(); - - $$.type = $1; - - TVariable* variable = 0; - if (context->nonInitErrorCheck(@2, *$2.string, $$.type, variable)) - context->recover(); - if (variable && symbol) - symbol->setId(variable->getUniqueId()); - } - | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET { - context->error(@2, "unsized array declarations not supported", $2.string->c_str()); - context->recover(); - - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); - $$.type = $1; - } - | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { - TType type = TType($1); - int size; - if (context->arraySizeErrorCheck(@2, $4, size)) - context->recover(); - type.setArraySize(size); - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, @2); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); - - if (context->structQualifierErrorCheck(@2, $1)) - context->recover(); - - if (context->nonInitConstErrorCheck(@2, *$2.string, $1, true)) - context->recover(); - - $$.type = $1; - - if (context->arrayTypeErrorCheck(@3, $1) || context->arrayQualifierErrorCheck(@3, $1)) - context->recover(); - else { - int size; - if (context->arraySizeErrorCheck(@3, $4, size)) - context->recover(); - - $1.setArray(true, size); - TVariable* variable = 0; - if (context->arrayErrorCheck(@3, *$2.string, $1, variable)) - context->recover(); - if (variable && symbol) - symbol->setId(variable->getUniqueId()); - } - } - | fully_specified_type identifier EQUAL initializer { - if (context->structQualifierErrorCheck(@2, $1)) - context->recover(); - - $$.type = $1; - - TIntermNode* intermNode; - if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode)) { - // - // Build intermediate representation - // - if(intermNode) - $$.intermAggregate = context->intermediate.makeAggregate(intermNode, @3); - else - $$.intermAggregate = 0; - } else { - context->recover(); - $$.intermAggregate = 0; - } - } - | INVARIANT IDENTIFIER { - VERTEX_ONLY("invariant declaration", @1); - if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying")) - context->recover(); - $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, @2); - if (!$2.symbol) - { - context->error(@2, "undeclared identifier declared as invariant", $2.string->c_str()); - context->recover(); - - $$.intermAggregate = 0; - } - else - { - TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), @2); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); - } - } - ; - -fully_specified_type - : type_specifier { - $$ = $1; - - if ($1.array) { - context->error(@1, "not supported", "first-class array"); - context->recover(); - $1.setArray(false); - } - } - | type_qualifier type_specifier { - if ($2.array) { - context->error(@2, "not supported", "first-class array"); - context->recover(); - $2.setArray(false); - } - - if ($1.qualifier == EvqAttribute && - ($2.type == EbtBool || $2.type == EbtInt)) { - context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier)); - context->recover(); - } - if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) && - ($2.type == EbtBool || $2.type == EbtInt)) { - context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier)); - context->recover(); - } - $$ = $2; - $$.qualifier = $1.qualifier; - } - ; - -type_qualifier - : CONST_QUAL { - $$.setBasic(EbtVoid, EvqConst, @1); - } - | ATTRIBUTE { - VERTEX_ONLY("attribute", @1); - if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "attribute")) - context->recover(); - $$.setBasic(EbtVoid, EvqAttribute, @1); - } - | VARYING { - if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "varying")) - context->recover(); - if (context->shaderType == SH_VERTEX_SHADER) - $$.setBasic(EbtVoid, EvqVaryingOut, @1); - else - $$.setBasic(EbtVoid, EvqVaryingIn, @1); - } - | INVARIANT VARYING { - if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying")) - context->recover(); - if (context->shaderType == SH_VERTEX_SHADER) - $$.setBasic(EbtVoid, EvqInvariantVaryingOut, @1); - else - $$.setBasic(EbtVoid, EvqInvariantVaryingIn, @1); - } - | UNIFORM { - if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "uniform")) - context->recover(); - $$.setBasic(EbtVoid, EvqUniform, @1); - } - ; - -type_specifier - : type_specifier_no_prec { - $$ = $1; - - if ($$.precision == EbpUndefined) { - $$.precision = context->symbolTable.getDefaultPrecision($1.type); - if (context->precisionErrorCheck(@1, $$.precision, $1.type)) { - context->recover(); - } - } - } - | precision_qualifier type_specifier_no_prec { - $$ = $2; - $$.precision = $1; - } - ; - -precision_qualifier - : HIGH_PRECISION { - $$ = EbpHigh; - } - | MEDIUM_PRECISION { - $$ = EbpMedium; - } - | LOW_PRECISION { - $$ = EbpLow; - } - ; - -type_specifier_no_prec - : type_specifier_nonarray { - $$ = $1; - } - | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET { - $$ = $1; - - if (context->arrayTypeErrorCheck(@2, $1)) - context->recover(); - else { - int size; - if (context->arraySizeErrorCheck(@2, $3, size)) - context->recover(); - $$.setArray(true, size); - } - } - ; - -type_specifier_nonarray - : VOID_TYPE { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtVoid, qual, @1); - } - | FLOAT_TYPE { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, @1); - } - | INT_TYPE { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtInt, qual, @1); - } - | BOOL_TYPE { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtBool, qual, @1); - } - | VEC2 { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, @1); - $$.setAggregate(2); - } - | VEC3 { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, @1); - $$.setAggregate(3); - } - | VEC4 { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, @1); - $$.setAggregate(4); - } - | BVEC2 { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtBool, qual, @1); - $$.setAggregate(2); - } - | BVEC3 { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtBool, qual, @1); - $$.setAggregate(3); - } - | BVEC4 { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtBool, qual, @1); - $$.setAggregate(4); - } - | IVEC2 { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtInt, qual, @1); - $$.setAggregate(2); - } - | IVEC3 { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtInt, qual, @1); - $$.setAggregate(3); - } - | IVEC4 { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtInt, qual, @1); - $$.setAggregate(4); - } - | MATRIX2 { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, @1); - $$.setAggregate(2, true); - } - | MATRIX3 { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, @1); - $$.setAggregate(3, true); - } - | MATRIX4 { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, @1); - $$.setAggregate(4, true); - } - | SAMPLER2D { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtSampler2D, qual, @1); - } - | SAMPLERCUBE { - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtSamplerCube, qual, @1); - } - | SAMPLER_EXTERNAL_OES { - if (!context->supportsExtension("GL_OES_EGL_image_external")) { - context->error(@1, "unsupported type", "samplerExternalOES"); - context->recover(); - } - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtSamplerExternalOES, qual, @1); - } - | SAMPLER2DRECT { - if (!context->supportsExtension("GL_ARB_texture_rectangle")) { - context->error(@1, "unsupported type", "sampler2DRect"); - context->recover(); - } - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtSampler2DRect, qual, @1); - } - | struct_specifier { - $$ = $1; - $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - } - | TYPE_NAME { - // - // This is for user defined type names. The lexical phase looked up the - // type. - // - TType& structure = static_cast($1.symbol)->getType(); - TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtStruct, qual, @1); - $$.userDef = &structure; - } - ; - -struct_specifier - : STRUCT identifier LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { - if (context->reservedErrorCheck(@2, *$2.string)) - context->recover(); - - TType* structure = new TType(new TStructure($2.string, $5)); - TVariable* userTypeDef = new TVariable($2.string, *structure, true); - if (! context->symbolTable.insert(*userTypeDef)) { - context->error(@2, "redefinition", $2.string->c_str(), "struct"); - context->recover(); - } - $$.setBasic(EbtStruct, EvqTemporary, @1); - $$.userDef = structure; - context->exitStructDeclaration(); - } - | STRUCT LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { - TType* structure = new TType(new TStructure(NewPoolTString(""), $4)); - $$.setBasic(EbtStruct, EvqTemporary, @1); - $$.userDef = structure; - context->exitStructDeclaration(); - } - ; - -struct_declaration_list - : struct_declaration { - $$ = $1; - } - | struct_declaration_list struct_declaration { - $$ = $1; - for (size_t i = 0; i < $2->size(); ++i) { - TField* field = (*$2)[i]; - for (size_t j = 0; j < $$->size(); ++j) { - if ((*$$)[j]->name() == field->name()) { - context->error(@2, "duplicate field name in structure:", "struct", field->name().c_str()); - context->recover(); - } - } - $$->push_back(field); - } - } - ; - -struct_declaration - : type_specifier struct_declarator_list SEMICOLON { - $$ = $2; - - if (context->voidErrorCheck(@1, (*$2)[0]->name(), $1)) { - context->recover(); - } - for (unsigned int i = 0; i < $$->size(); ++i) { - // - // Careful not to replace already known aspects of type, like array-ness - // - TType* type = (*$$)[i]->type(); - type->setBasicType($1.type); - type->setNominalSize($1.size); - type->setMatrix($1.matrix); - type->setPrecision($1.precision); - - // don't allow arrays of arrays - if (type->isArray()) { - if (context->arrayTypeErrorCheck(@1, $1)) - context->recover(); - } - if ($1.array) - type->setArraySize($1.arraySize); - if ($1.userDef) - type->setStruct($1.userDef->getStruct()); - - if (context->structNestingErrorCheck(@1, *(*$$)[i])) - context->recover(); - } - } - ; - -struct_declarator_list - : struct_declarator { - $$ = NewPoolTFieldList(); - $$->push_back($1); - } - | struct_declarator_list COMMA struct_declarator { - $$->push_back($3); - } - ; - -struct_declarator - : identifier { - if (context->reservedErrorCheck(@1, *$1.string)) - context->recover(); - - TType* type = new TType(EbtVoid, EbpUndefined); - $$ = new TField(type, $1.string); - } - | identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { - if (context->reservedErrorCheck(@1, *$1.string)) - context->recover(); - - TType* type = new TType(EbtVoid, EbpUndefined); - int size = 0; - if (context->arraySizeErrorCheck(@3, $3, size)) - context->recover(); - type->setArraySize(size); - - $$ = new TField(type, $1.string); - } - ; - -initializer - : assignment_expression { $$ = $1; } - ; - -declaration_statement - : declaration { $$ = $1; } - ; - -statement - : compound_statement { $$ = $1; } - | simple_statement { $$ = $1; } - ; - -// Grammar Note: No labeled statements; 'goto' is not supported. - -simple_statement - : declaration_statement { $$ = $1; } - | expression_statement { $$ = $1; } - | selection_statement { $$ = $1; } - | iteration_statement { $$ = $1; } - | jump_statement { $$ = $1; } - ; - -compound_statement - : LEFT_BRACE RIGHT_BRACE { $$ = 0; } - | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE { - if ($3 != 0) { - $3->setOp(EOpSequence); - $3->setLine(@$); - } - $$ = $3; - } - ; - -statement_no_new_scope - : compound_statement_no_new_scope { $$ = $1; } - | simple_statement { $$ = $1; } - ; - -statement_with_scope - : { context->symbolTable.push(); } compound_statement_no_new_scope { context->symbolTable.pop(); $$ = $2; } - | { context->symbolTable.push(); } simple_statement { context->symbolTable.pop(); $$ = $2; } - ; - -compound_statement_no_new_scope - // Statement that doesn't create a new scope, for selection_statement, iteration_statement - : LEFT_BRACE RIGHT_BRACE { - $$ = 0; - } - | LEFT_BRACE statement_list RIGHT_BRACE { - if ($2) { - $2->setOp(EOpSequence); - $2->setLine(@$); - } - $$ = $2; - } - ; - -statement_list - : statement { - $$ = context->intermediate.makeAggregate($1, @$); - } - | statement_list statement { - $$ = context->intermediate.growAggregate($1, $2, @$); - } - ; - -expression_statement - : SEMICOLON { $$ = 0; } - | expression SEMICOLON { $$ = static_cast($1); } - ; - -selection_statement - : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement { - if (context->boolErrorCheck(@1, $3)) - context->recover(); - $$ = context->intermediate.addSelection($3, $5, @1); - } - ; - -selection_rest_statement - : statement_with_scope ELSE statement_with_scope { - $$.node1 = $1; - $$.node2 = $3; - } - | statement_with_scope { - $$.node1 = $1; - $$.node2 = 0; - } - ; - -// Grammar Note: No 'switch'. Switch statements not supported. - -condition - // In 1996 c++ draft, conditions can include single declarations - : expression { - $$ = $1; - if (context->boolErrorCheck($1->getLine(), $1)) - context->recover(); - } - | fully_specified_type identifier EQUAL initializer { - TIntermNode* intermNode; - if (context->structQualifierErrorCheck(@2, $1)) - context->recover(); - if (context->boolErrorCheck(@2, $1)) - context->recover(); - - if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode)) - $$ = $4; - else { - context->recover(); - $$ = 0; - } - } - ; - -iteration_statement - : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope { - context->symbolTable.pop(); - $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, @1); - --context->loopNestingLevel; - } - | DO { ++context->loopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { - if (context->boolErrorCheck(@8, $6)) - context->recover(); - - $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4); - --context->loopNestingLevel; - } - | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { - context->symbolTable.pop(); - $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast($5.node1), reinterpret_cast($5.node2), $7, @1); - --context->loopNestingLevel; - } - ; - -for_init_statement - : expression_statement { - $$ = $1; - } - | declaration_statement { - $$ = $1; - } - ; - -conditionopt - : condition { - $$ = $1; - } - | /* May be null */ { - $$ = 0; - } - ; - -for_rest_statement - : conditionopt SEMICOLON { - $$.node1 = $1; - $$.node2 = 0; - } - | conditionopt SEMICOLON expression { - $$.node1 = $1; - $$.node2 = $3; - } - ; - -jump_statement - : CONTINUE SEMICOLON { - if (context->loopNestingLevel <= 0) { - context->error(@1, "continue statement only allowed in loops", ""); - context->recover(); - } - $$ = context->intermediate.addBranch(EOpContinue, @1); - } - | BREAK SEMICOLON { - if (context->loopNestingLevel <= 0) { - context->error(@1, "break statement only allowed in loops", ""); - context->recover(); - } - $$ = context->intermediate.addBranch(EOpBreak, @1); - } - | RETURN SEMICOLON { - $$ = context->intermediate.addBranch(EOpReturn, @1); - if (context->currentFunctionType->getBasicType() != EbtVoid) { - context->error(@1, "non-void function must return a value", "return"); - context->recover(); - } - } - | RETURN expression SEMICOLON { - $$ = context->intermediate.addBranch(EOpReturn, $2, @1); - context->functionReturnsValue = true; - if (context->currentFunctionType->getBasicType() == EbtVoid) { - context->error(@1, "void function cannot return a value", "return"); - context->recover(); - } else if (*(context->currentFunctionType) != $2->getType()) { - context->error(@1, "function return is not matching type:", "return"); - context->recover(); - } - } - | DISCARD SEMICOLON { - FRAG_ONLY("discard", @1); - $$ = context->intermediate.addBranch(EOpKill, @1); - } - ; - -// Grammar Note: No 'goto'. Gotos are not supported. - -translation_unit - : external_declaration { - $$ = $1; - context->treeRoot = $$; - } - | translation_unit external_declaration { - $$ = context->intermediate.growAggregate($1, $2, @$); - context->treeRoot = $$; - } - ; - -external_declaration - : function_definition { - $$ = $1; - } - | declaration { - $$ = $1; - } - ; - -function_definition - : function_prototype { - TFunction* function = $1.function; - - const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName()); - - if (builtIn) - { - context->error(@1, "built-in functions cannot be redefined", function->getName().c_str()); - context->recover(); - } - - 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(@1, "function already has a body", function->getName().c_str()); - context->recover(); - } - prevDec->setDefined(); - - // - // Raise error message if main function takes any parameters or return anything other than void - // - if (function->getName() == "main") { - if (function->getParamCount() > 0) { - context->error(@1, "function cannot take any parameter(s)", function->getName().c_str()); - context->recover(); - } - if (function->getReturnType().getBasicType() != EbtVoid) { - context->error(@1, "", function->getReturnType().getBasicString(), "main function cannot return a value"); - context->recover(); - } - } - - // - // Remember the return type for later checking for RETURN statements. - // - context->currentFunctionType = &(prevDec->getReturnType()); - context->functionReturnsValue = false; - - // - // Insert parameters into the symbol table. - // If the parameter has no name, it's not an error, just don't insert it - // (could be used for unused args). - // - // Also, accumulate the list of parameters into the HIL, so lower level code - // knows where to find parameters. - // - TIntermAggregate* paramNodes = new TIntermAggregate; - for (size_t i = 0; i < function->getParamCount(); i++) { - const TParameter& param = function->getParam(i); - if (param.name != 0) { - TVariable *variable = new TVariable(param.name, *param.type); - // - // Insert the parameters with name in the symbol table. - // - if (! context->symbolTable.insert(*variable)) { - context->error(@1, "redefinition", variable->getName().c_str()); - context->recover(); - delete variable; - } - - // - // Add the parameter to the HIL - // - paramNodes = context->intermediate.growAggregate( - paramNodes, - context->intermediate.addSymbol(variable->getUniqueId(), - variable->getName(), - variable->getType(), - @1), - @1); - } else { - paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, @1), @1); - } - } - context->intermediate.setAggregateOperator(paramNodes, EOpParameters, @1); - $1.intermAggregate = paramNodes; - context->loopNestingLevel = 0; - } - compound_statement_no_new_scope { - //?? Check that all paths return a value if return type != void ? - // May be best done as post process phase on intermediate code - if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) { - context->error(@1, "function does not return a value:", "", $1.function->getName().c_str()); - context->recover(); - } - - $$ = context->intermediate.growAggregate($1.intermAggregate, $3, @$); - context->intermediate.setAggregateOperator($$, EOpFunction, @1); - $$->getAsAggregate()->setName($1.function->getMangledName().c_str()); - $$->getAsAggregate()->setType($1.function->getReturnType()); - - // store the pragma information for debug and optimize and other vendor specific - // information. This information can be queried from the parse tree - $$->getAsAggregate()->setOptimize(context->pragma().optimize); - $$->getAsAggregate()->setDebug(context->pragma().debug); - - context->symbolTable.pop(); - } - ; - -%% - -int glslang_parse(TParseContext* context) { - return yyparse(context); -} diff --git a/src/3rdparty/angle/src/compiler/intermOut.cpp b/src/3rdparty/angle/src/compiler/intermOut.cpp deleted file mode 100644 index 13aa96af6d..0000000000 --- a/src/3rdparty/angle/src/compiler/intermOut.cpp +++ /dev/null @@ -1,424 +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. -// - -#include "compiler/localintermediate.h" - -// -// Two purposes: -// 1. Show an example of how to iterate tree. Functions can -// also directly call Traverse() on children themselves to -// have finer grained control over the process than shown here. -// See the last function for how to get started. -// 2. Print out a text based description of the tree. -// - -// -// Use this class to carry along data from node to node in -// the traversal -// -class TOutputTraverser : public TIntermTraverser { -public: - TOutputTraverser(TInfoSinkBase& i) : sink(i) { } - TInfoSinkBase& sink; - -protected: - void visitSymbol(TIntermSymbol*); - void visitConstantUnion(TIntermConstantUnion*); - bool visitBinary(Visit visit, TIntermBinary*); - bool visitUnary(Visit visit, TIntermUnary*); - bool visitSelection(Visit visit, TIntermSelection*); - bool visitAggregate(Visit visit, TIntermAggregate*); - bool visitLoop(Visit visit, TIntermLoop*); - bool visitBranch(Visit visit, TIntermBranch*); -}; - -TString TType::getCompleteString() const -{ - TStringStream stream; - - if (qualifier != EvqTemporary && qualifier != EvqGlobal) - stream << getQualifierString() << " " << getPrecisionString() << " "; - if (array) - stream << "array[" << getArraySize() << "] of "; - if (matrix) - stream << size << "X" << size << " matrix of "; - else if (size > 1) - stream << size << "-component vector of "; - - stream << getBasicString(); - return stream.str(); -} - -// -// Helper functions for printing, not part of traversing. -// - -void OutputTreeText(TInfoSinkBase& sink, TIntermNode* node, const int depth) -{ - int i; - - sink.location(node->getLine()); - - for (i = 0; i < depth; ++i) - sink << " "; -} - -// -// The rest of the file are the traversal functions. The last one -// is the one that starts the traversal. -// -// Return true from interior nodes to have the external traversal -// continue on to children. If you process children yourself, -// return false. -// - -void TOutputTraverser::visitSymbol(TIntermSymbol* node) -{ - OutputTreeText(sink, node, depth); - - sink << "'" << node->getSymbol() << "' "; - sink << "(" << node->getCompleteString() << ")\n"; -} - -bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node) -{ - TInfoSinkBase& out = sink; - - OutputTreeText(out, node, depth); - - switch (node->getOp()) { - case EOpAssign: out << "move second child to first child"; break; - case EOpInitialize: out << "initialize first child with second child"; break; - case EOpAddAssign: out << "add second child into first child"; break; - case EOpSubAssign: out << "subtract second child into first child"; break; - case EOpMulAssign: out << "multiply second child into first child"; break; - case EOpVectorTimesMatrixAssign: out << "matrix mult second child into first child"; break; - case EOpVectorTimesScalarAssign: out << "vector scale second child into first child"; break; - case EOpMatrixTimesScalarAssign: out << "matrix scale second child into first child"; break; - case EOpMatrixTimesMatrixAssign: out << "matrix mult second child into first child"; break; - case EOpDivAssign: out << "divide second child into first child"; break; - case EOpIndexDirect: out << "direct index"; break; - case EOpIndexIndirect: out << "indirect index"; break; - case EOpIndexDirectStruct: out << "direct index for structure"; break; - case EOpVectorSwizzle: out << "vector swizzle"; break; - - case EOpAdd: out << "add"; break; - case EOpSub: out << "subtract"; break; - case EOpMul: out << "component-wise multiply"; break; - case EOpDiv: out << "divide"; break; - case EOpEqual: out << "Compare Equal"; break; - case EOpNotEqual: out << "Compare Not Equal"; break; - case EOpLessThan: out << "Compare Less Than"; break; - case EOpGreaterThan: out << "Compare Greater Than"; break; - case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; - case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; - - case EOpVectorTimesScalar: out << "vector-scale"; break; - case EOpVectorTimesMatrix: out << "vector-times-matrix"; break; - case EOpMatrixTimesVector: out << "matrix-times-vector"; break; - case EOpMatrixTimesScalar: out << "matrix-scale"; break; - case EOpMatrixTimesMatrix: out << "matrix-multiply"; break; - - case EOpLogicalOr: out << "logical-or"; break; - case EOpLogicalXor: out << "logical-xor"; break; - case EOpLogicalAnd: out << "logical-and"; break; - default: out << ""; - } - - out << " (" << node->getCompleteString() << ")"; - - out << "\n"; - - return true; -} - -bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node) -{ - TInfoSinkBase& out = sink; - - OutputTreeText(out, node, depth); - - switch (node->getOp()) { - case EOpNegative: out << "Negate value"; break; - case EOpVectorLogicalNot: - case EOpLogicalNot: out << "Negate conditional"; break; - - case EOpPostIncrement: out << "Post-Increment"; break; - case EOpPostDecrement: out << "Post-Decrement"; break; - case EOpPreIncrement: out << "Pre-Increment"; break; - case EOpPreDecrement: out << "Pre-Decrement"; break; - - case EOpConvIntToBool: out << "Convert int to bool"; break; - case EOpConvFloatToBool:out << "Convert float to bool";break; - case EOpConvBoolToFloat:out << "Convert bool to float";break; - case EOpConvIntToFloat: out << "Convert int to float"; break; - case EOpConvFloatToInt: out << "Convert float to int"; break; - case EOpConvBoolToInt: out << "Convert bool to int"; break; - - case EOpRadians: out << "radians"; break; - case EOpDegrees: out << "degrees"; break; - case EOpSin: out << "sine"; break; - case EOpCos: out << "cosine"; break; - case EOpTan: out << "tangent"; break; - case EOpAsin: out << "arc sine"; break; - case EOpAcos: out << "arc cosine"; break; - case EOpAtan: out << "arc tangent"; break; - - case EOpExp: out << "exp"; break; - case EOpLog: out << "log"; break; - case EOpExp2: out << "exp2"; break; - case EOpLog2: out << "log2"; break; - case EOpSqrt: out << "sqrt"; break; - case EOpInverseSqrt: out << "inverse sqrt"; break; - - case EOpAbs: out << "Absolute value"; break; - case EOpSign: out << "Sign"; break; - case EOpFloor: out << "Floor"; break; - case EOpCeil: out << "Ceiling"; break; - case EOpFract: out << "Fraction"; break; - - case EOpLength: out << "length"; break; - case EOpNormalize: out << "normalize"; break; - // case EOpDPdx: out << "dPdx"; break; - // case EOpDPdy: out << "dPdy"; break; - // case EOpFwidth: out << "fwidth"; break; - - case EOpAny: out << "any"; break; - case EOpAll: out << "all"; break; - - default: - out.prefix(EPrefixError); - out << "Bad unary op"; - } - - out << " (" << node->getCompleteString() << ")"; - - out << "\n"; - - return true; -} - -bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node) -{ - TInfoSinkBase& out = sink; - - if (node->getOp() == EOpNull) { - out.prefix(EPrefixError); - out << "node is still EOpNull!"; - return true; - } - - OutputTreeText(out, node, depth); - - switch (node->getOp()) { - case EOpSequence: out << "Sequence\n"; return true; - case EOpComma: out << "Comma\n"; return true; - case EOpFunction: out << "Function Definition: " << node->getName(); break; - case EOpFunctionCall: out << "Function Call: " << node->getName(); break; - case EOpParameters: out << "Function Parameters: "; break; - - case EOpConstructFloat: out << "Construct float"; break; - case EOpConstructVec2: out << "Construct vec2"; break; - case EOpConstructVec3: out << "Construct vec3"; break; - case EOpConstructVec4: out << "Construct vec4"; break; - case EOpConstructBool: out << "Construct bool"; break; - case EOpConstructBVec2: out << "Construct bvec2"; break; - case EOpConstructBVec3: out << "Construct bvec3"; break; - case EOpConstructBVec4: out << "Construct bvec4"; break; - case EOpConstructInt: out << "Construct int"; break; - case EOpConstructIVec2: out << "Construct ivec2"; break; - case EOpConstructIVec3: out << "Construct ivec3"; break; - case EOpConstructIVec4: out << "Construct ivec4"; break; - case EOpConstructMat2: out << "Construct mat2"; break; - case EOpConstructMat3: out << "Construct mat3"; break; - case EOpConstructMat4: out << "Construct mat4"; break; - case EOpConstructStruct: out << "Construct structure"; break; - - case EOpLessThan: out << "Compare Less Than"; break; - case EOpGreaterThan: out << "Compare Greater Than"; break; - case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; - case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; - case EOpVectorEqual: out << "Equal"; break; - case EOpVectorNotEqual: out << "NotEqual"; break; - - case EOpMod: out << "mod"; break; - case EOpPow: out << "pow"; break; - - case EOpAtan: out << "arc tangent"; break; - - case EOpMin: out << "min"; break; - case EOpMax: out << "max"; break; - case EOpClamp: out << "clamp"; break; - case EOpMix: out << "mix"; break; - case EOpStep: out << "step"; break; - case EOpSmoothStep: out << "smoothstep"; break; - - case EOpDistance: out << "distance"; break; - case EOpDot: out << "dot-product"; break; - case EOpCross: out << "cross-product"; break; - case EOpFaceForward: out << "face-forward"; break; - case EOpReflect: out << "reflect"; break; - case EOpRefract: out << "refract"; break; - case EOpMul: out << "component-wise multiply"; break; - - case EOpDeclaration: out << "Declaration: "; break; - - default: - out.prefix(EPrefixError); - out << "Bad aggregation op"; - } - - if (node->getOp() != EOpSequence && node->getOp() != EOpParameters) - out << " (" << node->getCompleteString() << ")"; - - out << "\n"; - - return true; -} - -bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node) -{ - TInfoSinkBase& out = sink; - - OutputTreeText(out, node, depth); - - out << "Test condition and select"; - out << " (" << node->getCompleteString() << ")\n"; - - ++depth; - - OutputTreeText(sink, node, depth); - out << "Condition\n"; - node->getCondition()->traverse(this); - - OutputTreeText(sink, node, depth); - if (node->getTrueBlock()) { - out << "true case\n"; - node->getTrueBlock()->traverse(this); - } else - out << "true case is null\n"; - - if (node->getFalseBlock()) { - OutputTreeText(sink, node, depth); - out << "false case\n"; - node->getFalseBlock()->traverse(this); - } - - --depth; - - return false; -} - -void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) -{ - TInfoSinkBase& out = sink; - - size_t size = node->getType().getObjectSize(); - - for (size_t i = 0; i < size; i++) { - OutputTreeText(out, node, depth); - switch (node->getUnionArrayPointer()[i].getType()) { - case EbtBool: - if (node->getUnionArrayPointer()[i].getBConst()) - out << "true"; - else - out << "false"; - - out << " (" << "const bool" << ")"; - out << "\n"; - break; - case EbtFloat: - out << node->getUnionArrayPointer()[i].getFConst(); - out << " (const float)\n"; - break; - case EbtInt: - out << node->getUnionArrayPointer()[i].getIConst(); - out << " (const int)\n"; - break; - default: - out.message(EPrefixInternalError, node->getLine(), "Unknown constant"); - break; - } - } -} - -bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node) -{ - TInfoSinkBase& out = sink; - - OutputTreeText(out, node, depth); - - out << "Loop with condition "; - if (node->getType() == ELoopDoWhile) - out << "not "; - out << "tested first\n"; - - ++depth; - - OutputTreeText(sink, node, depth); - if (node->getCondition()) { - out << "Loop Condition\n"; - node->getCondition()->traverse(this); - } else - out << "No loop condition\n"; - - OutputTreeText(sink, node, depth); - if (node->getBody()) { - out << "Loop Body\n"; - node->getBody()->traverse(this); - } else - out << "No loop body\n"; - - if (node->getExpression()) { - OutputTreeText(sink, node, depth); - out << "Loop Terminal Expression\n"; - node->getExpression()->traverse(this); - } - - --depth; - - return false; -} - -bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node) -{ - TInfoSinkBase& out = sink; - - OutputTreeText(out, node, depth); - - switch (node->getFlowOp()) { - case EOpKill: out << "Branch: Kill"; break; - case EOpBreak: out << "Branch: Break"; break; - case EOpContinue: out << "Branch: Continue"; break; - case EOpReturn: out << "Branch: Return"; break; - default: out << "Branch: Unknown Branch"; break; - } - - if (node->getExpression()) { - out << " with expression\n"; - ++depth; - node->getExpression()->traverse(this); - --depth; - } else - out << "\n"; - - return false; -} - -// -// This function is the one to call externally to start the traversal. -// Individual functions can be initialized to 0 to skip processing of that -// type of node. It's children will still be processed. -// -void TIntermediate::outputTree(TIntermNode* root) -{ - if (root == 0) - return; - - TOutputTraverser it(infoSink.info); - - root->traverse(&it); -} diff --git a/src/3rdparty/angle/src/compiler/intermediate.h b/src/3rdparty/angle/src/compiler/intermediate.h deleted file mode 100644 index 738621fe70..0000000000 --- a/src/3rdparty/angle/src/compiler/intermediate.h +++ /dev/null @@ -1,579 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// Definition of the in-memory high-level intermediate representation -// of shaders. This is a tree that parser creates. -// -// Nodes in the tree are defined as a hierarchy of classes derived from -// TIntermNode. Each is a node in a tree. There is no preset branching factor; -// each node can have it's own type of list of children. -// - -#ifndef __INTERMEDIATE_H -#define __INTERMEDIATE_H - -#include "GLSLANG/ShaderLang.h" - -#include -#include "compiler/Common.h" -#include "compiler/Types.h" -#include "compiler/ConstantUnion.h" - -// -// Operators used by the high-level (parse tree) representation. -// -enum TOperator { - EOpNull, // if in a node, should only mean a node is still being built - EOpSequence, // denotes a list of statements, or parameters, etc. - EOpFunctionCall, - EOpFunction, // For function definition - EOpParameters, // an aggregate listing the parameters to a function - - EOpDeclaration, - EOpPrototype, - - // - // Unary operators - // - - EOpNegative, - EOpLogicalNot, - EOpVectorLogicalNot, - - EOpPostIncrement, - EOpPostDecrement, - EOpPreIncrement, - EOpPreDecrement, - - EOpConvIntToBool, - EOpConvFloatToBool, - EOpConvBoolToFloat, - EOpConvIntToFloat, - EOpConvFloatToInt, - EOpConvBoolToInt, - - // - // binary operations - // - - EOpAdd, - EOpSub, - EOpMul, - EOpDiv, - EOpEqual, - EOpNotEqual, - EOpVectorEqual, - EOpVectorNotEqual, - EOpLessThan, - EOpGreaterThan, - EOpLessThanEqual, - EOpGreaterThanEqual, - EOpComma, - - EOpVectorTimesScalar, - EOpVectorTimesMatrix, - EOpMatrixTimesVector, - EOpMatrixTimesScalar, - - EOpLogicalOr, - EOpLogicalXor, - EOpLogicalAnd, - - EOpIndexDirect, - EOpIndexIndirect, - EOpIndexDirectStruct, - - EOpVectorSwizzle, - - // - // Built-in functions potentially mapped to operators - // - - EOpRadians, - EOpDegrees, - EOpSin, - EOpCos, - EOpTan, - EOpAsin, - EOpAcos, - EOpAtan, - - EOpPow, - EOpExp, - EOpLog, - EOpExp2, - EOpLog2, - EOpSqrt, - EOpInverseSqrt, - - EOpAbs, - EOpSign, - EOpFloor, - EOpCeil, - EOpFract, - EOpMod, - EOpMin, - EOpMax, - EOpClamp, - EOpMix, - EOpStep, - EOpSmoothStep, - - EOpLength, - EOpDistance, - EOpDot, - EOpCross, - EOpNormalize, - EOpFaceForward, - EOpReflect, - EOpRefract, - - EOpDFdx, // Fragment only, OES_standard_derivatives extension - EOpDFdy, // Fragment only, OES_standard_derivatives extension - EOpFwidth, // Fragment only, OES_standard_derivatives extension - - EOpMatrixTimesMatrix, - - EOpAny, - EOpAll, - - // - // Branch - // - - EOpKill, // Fragment only - EOpReturn, - EOpBreak, - EOpContinue, - - // - // Constructors - // - - EOpConstructInt, - EOpConstructBool, - EOpConstructFloat, - EOpConstructVec2, - EOpConstructVec3, - EOpConstructVec4, - EOpConstructBVec2, - EOpConstructBVec3, - EOpConstructBVec4, - EOpConstructIVec2, - EOpConstructIVec3, - EOpConstructIVec4, - EOpConstructMat2, - EOpConstructMat3, - EOpConstructMat4, - EOpConstructStruct, - - // - // moves - // - - EOpAssign, - EOpInitialize, - EOpAddAssign, - EOpSubAssign, - EOpMulAssign, - EOpVectorTimesMatrixAssign, - EOpVectorTimesScalarAssign, - EOpMatrixTimesScalarAssign, - EOpMatrixTimesMatrixAssign, - EOpDivAssign -}; - -extern const char* getOperatorString(TOperator op); - -class TIntermTraverser; -class TIntermAggregate; -class TIntermBinary; -class TIntermUnary; -class TIntermConstantUnion; -class TIntermSelection; -class TIntermTyped; -class TIntermSymbol; -class TIntermLoop; -class TInfoSink; - -// -// Base class for the tree nodes -// -class TIntermNode { -public: - POOL_ALLOCATOR_NEW_DELETE(); - TIntermNode() { - // TODO: Move this to TSourceLoc constructor - // after getting rid of TPublicType. - line.first_file = line.last_file = 0; - line.first_line = line.last_line = 0; - } - virtual ~TIntermNode() { } - - const TSourceLoc& getLine() const { return line; } - void setLine(const TSourceLoc& l) { line = l; } - - virtual void traverse(TIntermTraverser*) = 0; - virtual TIntermTyped* getAsTyped() { return 0; } - virtual TIntermConstantUnion* getAsConstantUnion() { return 0; } - virtual TIntermAggregate* getAsAggregate() { return 0; } - virtual TIntermBinary* getAsBinaryNode() { return 0; } - virtual TIntermUnary* getAsUnaryNode() { return 0; } - virtual TIntermSelection* getAsSelectionNode() { return 0; } - virtual TIntermSymbol* getAsSymbolNode() { return 0; } - virtual TIntermLoop* getAsLoopNode() { return 0; } - -protected: - TSourceLoc line; -}; - -// -// This is just to help yacc. -// -struct TIntermNodePair { - TIntermNode* node1; - TIntermNode* node2; -}; - -// -// Intermediate class for nodes that have a type. -// -class TIntermTyped : public TIntermNode { -public: - TIntermTyped(const TType& t) : type(t) { } - virtual TIntermTyped* getAsTyped() { return this; } - - void setType(const TType& t) { type = t; } - const TType& getType() const { return type; } - TType* getTypePointer() { return &type; } - - TBasicType getBasicType() const { return type.getBasicType(); } - TQualifier getQualifier() const { return type.getQualifier(); } - TPrecision getPrecision() const { return type.getPrecision(); } - int getNominalSize() const { return type.getNominalSize(); } - - bool isMatrix() const { return type.isMatrix(); } - bool isArray() const { return type.isArray(); } - bool isVector() const { return type.isVector(); } - bool isScalar() const { return type.isScalar(); } - const char* getBasicString() const { return type.getBasicString(); } - const char* getQualifierString() const { return type.getQualifierString(); } - TString getCompleteString() const { return type.getCompleteString(); } - - int totalRegisterCount() const { return type.totalRegisterCount(); } - int elementRegisterCount() const { return type.elementRegisterCount(); } - int getArraySize() const { return type.getArraySize(); } - -protected: - TType type; -}; - -// -// Handle for, do-while, and while loops. -// -enum TLoopType { - ELoopFor, - ELoopWhile, - ELoopDoWhile -}; - -class TIntermLoop : public TIntermNode { -public: - TIntermLoop(TLoopType aType, - TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr, - TIntermNode* aBody) : - type(aType), - init(aInit), - cond(aCond), - expr(aExpr), - body(aBody), - unrollFlag(false) { } - - virtual TIntermLoop* getAsLoopNode() { return this; } - virtual void traverse(TIntermTraverser*); - - TLoopType getType() const { return type; } - TIntermNode* getInit() { return init; } - TIntermTyped* getCondition() { return cond; } - TIntermTyped* getExpression() { return expr; } - TIntermNode* getBody() { return body; } - - void setUnrollFlag(bool flag) { unrollFlag = flag; } - bool getUnrollFlag() { return unrollFlag; } - -protected: - TLoopType type; - TIntermNode* init; // for-loop initialization - TIntermTyped* cond; // loop exit condition - TIntermTyped* expr; // for-loop expression - TIntermNode* body; // loop body - - bool unrollFlag; // Whether the loop should be unrolled or not. -}; - -// -// Handle break, continue, return, and kill. -// -class TIntermBranch : public TIntermNode { -public: - TIntermBranch(TOperator op, TIntermTyped* e) : - flowOp(op), - expression(e) { } - - virtual void traverse(TIntermTraverser*); - - TOperator getFlowOp() { return flowOp; } - TIntermTyped* getExpression() { return expression; } - -protected: - TOperator flowOp; - TIntermTyped* expression; // non-zero except for "return exp;" statements -}; - -// -// Nodes that correspond to symbols or constants in the source code. -// -class TIntermSymbol : public TIntermTyped { -public: - // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from - // per process globalpoolallocator, then it causes increased memory usage per compile - // it is essential to use "symbol = sym" to assign to symbol - TIntermSymbol(int i, const TString& sym, const TType& t) : - TIntermTyped(t), id(i) { symbol = sym; originalSymbol = sym; } - - int getId() const { return id; } - const TString& getSymbol() const { return symbol; } - - void setId(int newId) { id = newId; } - void setSymbol(const TString& sym) { symbol = sym; } - - const TString& getOriginalSymbol() const { return originalSymbol; } - - virtual void traverse(TIntermTraverser*); - virtual TIntermSymbol* getAsSymbolNode() { return this; } - -protected: - int id; - TString symbol; - TString originalSymbol; -}; - -class TIntermConstantUnion : public TIntermTyped { -public: - TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { } - - ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; } - - int getIConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; } - float getFConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; } - bool getBConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; } - - virtual TIntermConstantUnion* getAsConstantUnion() { return this; } - virtual void traverse(TIntermTraverser*); - - TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&); - -protected: - ConstantUnion *unionArrayPointer; -}; - -// -// Intermediate class for node types that hold operators. -// -class TIntermOperator : public TIntermTyped { -public: - TOperator getOp() const { return op; } - void setOp(TOperator o) { op = o; } - - bool modifiesState() const; - bool isConstructor() const; - -protected: - TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {} - TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {} - TOperator op; -}; - -// -// Nodes for all the basic binary math operators. -// -class TIntermBinary : public TIntermOperator { -public: - TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {} - - virtual TIntermBinary* getAsBinaryNode() { return this; } - virtual void traverse(TIntermTraverser*); - - void setLeft(TIntermTyped* n) { left = n; } - void setRight(TIntermTyped* n) { right = n; } - TIntermTyped* getLeft() const { return left; } - TIntermTyped* getRight() const { return right; } - bool promote(TInfoSink&); - - void setAddIndexClamp() { addIndexClamp = true; } - bool getAddIndexClamp() { return addIndexClamp; } - -protected: - TIntermTyped* left; - TIntermTyped* right; - - // If set to true, wrap any EOpIndexIndirect with a clamp to bounds. - bool addIndexClamp; -}; - -// -// Nodes for unary math operators. -// -class TIntermUnary : public TIntermOperator { -public: - TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {} - TIntermUnary(TOperator o) : TIntermOperator(o), operand(0), useEmulatedFunction(false) {} - - virtual void traverse(TIntermTraverser*); - virtual TIntermUnary* getAsUnaryNode() { return this; } - - void setOperand(TIntermTyped* o) { operand = o; } - TIntermTyped* getOperand() { return operand; } - bool promote(TInfoSink&); - - void setUseEmulatedFunction() { useEmulatedFunction = true; } - bool getUseEmulatedFunction() { return useEmulatedFunction; } - -protected: - TIntermTyped* operand; - - // If set to true, replace the built-in function call with an emulated one - // to work around driver bugs. - bool useEmulatedFunction; -}; - -typedef TVector TIntermSequence; -typedef TVector TQualifierList; - -// -// Nodes that operate on an arbitrary sized set of children. -// -class TIntermAggregate : public TIntermOperator { -public: - TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { } - TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { } - ~TIntermAggregate() { } - - virtual TIntermAggregate* getAsAggregate() { return this; } - virtual void traverse(TIntermTraverser*); - - TIntermSequence& getSequence() { return sequence; } - - void setName(const TString& n) { name = n; } - const TString& getName() const { return name; } - - void setUserDefined() { userDefined = true; } - bool isUserDefined() const { return userDefined; } - - void setOptimize(bool o) { optimize = o; } - bool getOptimize() { return optimize; } - void setDebug(bool d) { debug = d; } - bool getDebug() { return debug; } - - void setUseEmulatedFunction() { useEmulatedFunction = true; } - bool getUseEmulatedFunction() { return useEmulatedFunction; } - -protected: - TIntermAggregate(const TIntermAggregate&); // disallow copy constructor - TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator - TIntermSequence sequence; - TString name; - bool userDefined; // used for user defined function names - - bool optimize; - bool debug; - - // If set to true, replace the built-in function call with an emulated one - // to work around driver bugs. - bool useEmulatedFunction; -}; - -// -// For if tests. Simplified since there is no switch statement. -// -class TIntermSelection : public TIntermTyped { -public: - TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : - TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {} - TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : - TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {} - - virtual void traverse(TIntermTraverser*); - - bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } - TIntermNode* getCondition() const { return condition; } - TIntermNode* getTrueBlock() const { return trueBlock; } - TIntermNode* getFalseBlock() const { return falseBlock; } - TIntermSelection* getAsSelectionNode() { return this; } - -protected: - TIntermTyped* condition; - TIntermNode* trueBlock; - TIntermNode* falseBlock; -}; - -enum Visit -{ - PreVisit, - InVisit, - PostVisit -}; - -// -// For traversing the tree. User should derive from this, -// put their traversal specific data in it, and then pass -// it to a Traverse method. -// -// When using this, just fill in the methods for nodes you want visited. -// Return false from a pre-visit to skip visiting that node's subtree. -// -class TIntermTraverser -{ -public: - POOL_ALLOCATOR_NEW_DELETE(); - TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : - preVisit(preVisit), - inVisit(inVisit), - postVisit(postVisit), - rightToLeft(rightToLeft), - depth(0), - maxDepth(0) {} - virtual ~TIntermTraverser() {}; - - virtual void visitSymbol(TIntermSymbol*) {} - virtual void visitConstantUnion(TIntermConstantUnion*) {} - virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;} - virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;} - virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;} - virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;} - virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;} - virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;} - - int getMaxDepth() const {return maxDepth;} - void incrementDepth() {depth++; maxDepth = std::max(maxDepth, depth); } - void decrementDepth() {depth--;} - - // Return the original name if hash function pointer is NULL; - // otherwise return the hashed name. - static TString hash(const TString& name, ShHashFunction64 hashFunction); - - const bool preVisit; - const bool inVisit; - const bool postVisit; - const bool rightToLeft; - -protected: - int depth; - int maxDepth; -}; - -#endif // __INTERMEDIATE_H diff --git a/src/3rdparty/angle/src/compiler/localintermediate.h b/src/3rdparty/angle/src/compiler/localintermediate.h deleted file mode 100644 index 1214d821eb..0000000000 --- a/src/3rdparty/angle/src/compiler/localintermediate.h +++ /dev/null @@ -1,57 +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. -// - -#ifndef _LOCAL_INTERMEDIATE_INCLUDED_ -#define _LOCAL_INTERMEDIATE_INCLUDED_ - -#include "GLSLANG/ShaderLang.h" -#include "compiler/intermediate.h" -#include "compiler/SymbolTable.h" - -struct TVectorFields { - int offsets[4]; - int num; -}; - -// -// Set of helper functions to help parse and build the tree. -// -class TInfoSink; -class TIntermediate { -public: - POOL_ALLOCATOR_NEW_DELETE(); - TIntermediate(TInfoSink& i) : infoSink(i) { } - - TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TSourceLoc&); - TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); - TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&, TSymbolTable&); - TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); - TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&); - TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, const TSourceLoc&, TSymbolTable&); - TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&); - TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&); - TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, const TSourceLoc&); - TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&); - TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&); - TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); - TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, const TSourceLoc&); - TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ; - bool parseConstTree(const TSourceLoc&, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false); - TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, const TSourceLoc&); - TIntermBranch* addBranch(TOperator, const TSourceLoc&); - TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&); - TIntermTyped* addSwizzle(TVectorFields&, const TSourceLoc&); - bool postProcess(TIntermNode*); - void remove(TIntermNode*); - void outputTree(TIntermNode*); - -private: - void operator=(TIntermediate&); // prevent assignments - - TInfoSink& infoSink; -}; - -#endif // _LOCAL_INTERMEDIATE_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/osinclude.h b/src/3rdparty/angle/src/compiler/osinclude.h deleted file mode 100644 index 60177d5fe5..0000000000 --- a/src/3rdparty/angle/src/compiler/osinclude.h +++ /dev/null @@ -1,58 +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. -// - -#ifndef __OSINCLUDE_H -#define __OSINCLUDE_H - -// -// This file contains contains os-specific datatypes and -// declares any os-specific functions. -// - -#if defined(_WIN32) || defined(_WIN64) -#define STRICT -#define VC_EXTRALEAN 1 -#include -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) -#define ANGLE_OS_WINRT -#else -#define ANGLE_OS_WIN -#endif -#elif defined(__APPLE__) || defined(__linux__) || \ - defined(__FreeBSD__) || defined(__OpenBSD__) || \ - defined(__sun) || defined(ANDROID) || \ - defined(__GLIBC__) || defined(__GNU__) || \ - defined(__QNX__) -#define ANGLE_OS_POSIX -#include -#include -#include -#else -#error Unsupported platform. -#endif - -#include "compiler/debug.h" - -// -// Thread Local Storage Operations -// -#if defined(ANGLE_OS_WIN) -typedef DWORD OS_TLSIndex; -#define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES) -#elif defined(ANGLE_OS_WINRT) -typedef size_t OS_TLSIndex; -#define OS_INVALID_TLS_INDEX ((DWORD)0xFFFFFF) -#elif defined(ANGLE_OS_POSIX) -typedef pthread_key_t OS_TLSIndex; -#define OS_INVALID_TLS_INDEX (static_cast(-1)) -#endif // ANGLE_OS_WIN - -OS_TLSIndex OS_AllocTLSIndex(); -void *OS_GetTLSValue(OS_TLSIndex nIndex); -bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue); -bool OS_FreeTLSIndex(OS_TLSIndex nIndex); - -#endif // __OSINCLUDE_H diff --git a/src/3rdparty/angle/src/compiler/ossource_posix.cpp b/src/3rdparty/angle/src/compiler/ossource_posix.cpp deleted file mode 100644 index 35510c1af5..0000000000 --- a/src/3rdparty/angle/src/compiler/ossource_posix.cpp +++ /dev/null @@ -1,72 +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. -// - -// -// This file contains the posix specific functions -// -#include "compiler/osinclude.h" - -#if !defined(ANGLE_OS_POSIX) -#error Trying to build a posix specific file in a non-posix build. -#endif - -// -// Thread Local Storage Operations -// -OS_TLSIndex OS_AllocTLSIndex() -{ - pthread_key_t pPoolIndex; - - // - // Create global pool key. - // - if ((pthread_key_create(&pPoolIndex, NULL)) != 0) { - assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage"); - return false; - } - else { - return pPoolIndex; - } -} - - -void *OS_GetTLSValue(OS_TLSIndex nIndex) -{ - ASSERT(nIndex != OS_INVALID_TLS_INDEX); - - return pthread_getspecific(nIndex); -} - - -bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) -{ - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - if (pthread_setspecific(nIndex, lpvValue) == 0) - return true; - else - return false; -} - - -bool OS_FreeTLSIndex(OS_TLSIndex nIndex) -{ - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - // - // Delete the global pool key. - // - if (pthread_key_delete(nIndex) == 0) - return true; - else - return false; -} diff --git a/src/3rdparty/angle/src/compiler/ossource_win.cpp b/src/3rdparty/angle/src/compiler/ossource_win.cpp deleted file mode 100644 index 708a1ad311..0000000000 --- a/src/3rdparty/angle/src/compiler/ossource_win.cpp +++ /dev/null @@ -1,65 +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. -// - -#include "compiler/osinclude.h" -// -// This file contains contains the window's specific functions -// - -#if !defined(ANGLE_OS_WIN) -#error Trying to build a windows specific file in a non windows build. -#endif - - -// -// Thread Local Storage Operations -// -OS_TLSIndex OS_AllocTLSIndex() -{ - DWORD dwIndex = TlsAlloc(); - if (dwIndex == TLS_OUT_OF_INDEXES) { - assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage"); - return OS_INVALID_TLS_INDEX; - } - - return dwIndex; -} - - -void *OS_GetTLSValue(OS_TLSIndex nIndex) -{ - ASSERT(nIndex != OS_INVALID_TLS_INDEX); - - return TlsGetValue(nIndex); -} - - -bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) -{ - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - if (TlsSetValue(nIndex, lpvValue)) - return true; - else - return false; -} - - -bool OS_FreeTLSIndex(OS_TLSIndex nIndex) -{ - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - if (TlsFree(nIndex)) - return true; - else - return false; -} diff --git a/src/3rdparty/angle/src/compiler/ossource_winrt.cpp b/src/3rdparty/angle/src/compiler/ossource_winrt.cpp deleted file mode 100644 index 84443abc02..0000000000 --- a/src/3rdparty/angle/src/compiler/ossource_winrt.cpp +++ /dev/null @@ -1,75 +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. -// - -#include "compiler/osinclude.h" -// -// This file contains contains Windows Runtime specific functions -// - -#if !defined(ANGLE_OS_WINRT) -#error Trying to build a WinRT specific file in a non-WinRT build. -#endif - -#include - - -// -// Thread Local Storage Operations -// -__declspec(thread) std::vector *tls = nullptr; -__declspec(thread) std::vector *freeIndices = nullptr; - -OS_TLSIndex OS_AllocTLSIndex() -{ - if (!tls) - tls = new std::vector; - - if (freeIndices && !freeIndices->empty()) { - OS_TLSIndex index = freeIndices->back(); - freeIndices->pop_back(); - return index; - } else { - tls->push_back(nullptr); - return tls->size() - 1; - } -} - - -void *OS_GetTLSValue(OS_TLSIndex nIndex) -{ - ASSERT(nIndex != OS_INVALID_TLS_INDEX); - ASSERT(tls); - - return tls->at(nIndex); -} - - -bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) -{ - if (!tls || nIndex >= tls->size() || nIndex == OS_INVALID_TLS_INDEX) { - ASSERT(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - tls->at(nIndex) = lpvValue; - return true; -} - - -bool OS_FreeTLSIndex(OS_TLSIndex nIndex) -{ - if (!tls || nIndex >= tls->size() || nIndex == OS_INVALID_TLS_INDEX) { - ASSERT(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - if (!freeIndices) - freeIndices = new std::vector; - - freeIndices->push_back(nIndex); - - return true; -} diff --git a/src/3rdparty/angle/src/compiler/parseConst.cpp b/src/3rdparty/angle/src/compiler/parseConst.cpp deleted file mode 100644 index 1cc5db8d77..0000000000 --- a/src/3rdparty/angle/src/compiler/parseConst.cpp +++ /dev/null @@ -1,245 +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. -// - -#include "compiler/ParseHelper.h" - -// -// Use this class to carry along data from node to node in -// the traversal -// -class TConstTraverser : public TIntermTraverser { -public: - TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t) - : error(false), - index(0), - unionArray(cUnion), - type(t), - constructorType(constructType), - singleConstantParam(singleConstParam), - infoSink(sink), - symbolTable(symTable), - size(0), - isMatrix(false), - matrixSize(0) { - } - - bool error; - -protected: - void visitSymbol(TIntermSymbol*); - void visitConstantUnion(TIntermConstantUnion*); - bool visitBinary(Visit visit, TIntermBinary*); - bool visitUnary(Visit visit, TIntermUnary*); - bool visitSelection(Visit visit, TIntermSelection*); - bool visitAggregate(Visit visit, TIntermAggregate*); - bool visitLoop(Visit visit, TIntermLoop*); - bool visitBranch(Visit visit, TIntermBranch*); - - size_t index; - ConstantUnion *unionArray; - TType type; - TOperator constructorType; - bool singleConstantParam; - TInfoSink& infoSink; - TSymbolTable& symbolTable; - size_t size; // size of the constructor ( 4 for vec4) - bool isMatrix; - size_t matrixSize; // dimension of the matrix (nominal size and not the instance size) -}; - -// -// The rest of the file are the traversal functions. The last one -// is the one that starts the traversal. -// -// Return true from interior nodes to have the external traversal -// continue on to children. If you process children yourself, -// return false. -// - -void TConstTraverser::visitSymbol(TIntermSymbol* node) -{ - infoSink.info.message(EPrefixInternalError, node->getLine(), "Symbol Node found in constant constructor"); - return; - -} - -bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node) -{ - TQualifier qualifier = node->getType().getQualifier(); - - if (qualifier != EvqConst) { - TString buf; - buf.append("'constructor' : assigning non-constant to "); - buf.append(type.getCompleteString()); - infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); - error = true; - return false; - } - - infoSink.info.message(EPrefixInternalError, node->getLine(), "Binary Node found in constant constructor"); - - return false; -} - -bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node) -{ - TString buf; - buf.append("'constructor' : assigning non-constant to "); - buf.append(type.getCompleteString()); - infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); - error = true; - return false; -} - -bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node) -{ - if (!node->isConstructor() && node->getOp() != EOpComma) { - TString buf; - buf.append("'constructor' : assigning non-constant to "); - buf.append(type.getCompleteString()); - infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); - error = true; - return false; - } - - if (node->getSequence().size() == 0) { - error = true; - return false; - } - - bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion(); - if (flag) - { - singleConstantParam = true; - constructorType = node->getOp(); - size = node->getType().getObjectSize(); - - if (node->getType().isMatrix()) { - isMatrix = true; - matrixSize = node->getType().getNominalSize(); - } - } - - for (TIntermSequence::iterator p = node->getSequence().begin(); - p != node->getSequence().end(); p++) { - - if (node->getOp() == EOpComma) - index = 0; - - (*p)->traverse(this); - } - if (flag) - { - singleConstantParam = false; - constructorType = EOpNull; - size = 0; - isMatrix = false; - matrixSize = 0; - } - return false; -} - -bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node) -{ - infoSink.info.message(EPrefixInternalError, node->getLine(), "Selection Node found in constant constructor"); - error = true; - return false; -} - -void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) -{ - if (!node->getUnionArrayPointer()) - { - // The constant was not initialized, this should already have been logged - assert(infoSink.info.size() != 0); - return; - } - - ConstantUnion* leftUnionArray = unionArray; - size_t instanceSize = type.getObjectSize(); - - if (index >= instanceSize) - return; - - if (!singleConstantParam) { - size_t size = node->getType().getObjectSize(); - - ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); - for (size_t i = 0; i < size; i++) { - if (index >= instanceSize) - return; - leftUnionArray[index] = rightUnionArray[i]; - - (index)++; - } - } else { - size_t totalSize = index + size; - ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); - if (!isMatrix) { - size_t count = 0; - for (size_t i = index; i < totalSize; i++) { - if (i >= instanceSize) - return; - - leftUnionArray[i] = rightUnionArray[count]; - - (index)++; - - if (node->getType().getObjectSize() > 1) - count++; - } - } else { // for matrix constructors - size_t count = 0; - size_t element = index; - for (size_t i = index; i < totalSize; i++) { - if (i >= instanceSize) - return; - if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 ) - leftUnionArray[i] = rightUnionArray[count]; - else - leftUnionArray[i].setFConst(0.0f); - - (index)++; - - if (node->getType().getObjectSize() > 1) - count++; - } - } - } -} - -bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node) -{ - infoSink.info.message(EPrefixInternalError, node->getLine(), "Loop Node found in constant constructor"); - error = true; - return false; -} - -bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node) -{ - infoSink.info.message(EPrefixInternalError, node->getLine(), "Branch Node found in constant constructor"); - error = true; - return false; -} - -// -// This function is the one to call externally to start the traversal. -// Individual functions can be initialized to 0 to skip processing of that -// type of node. It's children will still be processed. -// -bool TIntermediate::parseConstTree(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam) -{ - if (root == 0) - return false; - - TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t); - - root->traverse(&it); - if (it.error) - return true; - else - return false; -} diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp index 3e22e1f1c5..a7ce862bcb 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp @@ -25,14 +25,14 @@ void Diagnostics::report(ID id, Diagnostics::Severity Diagnostics::severity(ID id) { - if ((id > ERROR_BEGIN) && (id < ERROR_END)) - return ERROR; + if ((id > PP_ERROR_BEGIN) && (id < PP_ERROR_END)) + return PP_ERROR; - if ((id > WARNING_BEGIN) && (id < WARNING_END)) - return WARNING; + if ((id > PP_WARNING_BEGIN) && (id < PP_WARNING_END)) + return PP_WARNING; assert(false); - return ERROR; + return PP_ERROR; } std::string Diagnostics::message(ID id) @@ -40,82 +40,82 @@ std::string Diagnostics::message(ID id) switch (id) { // Errors begin. - case INTERNAL_ERROR: + case PP_INTERNAL_ERROR: return "internal error"; - case OUT_OF_MEMORY: + case PP_OUT_OF_MEMORY: return "out of memory"; - case INVALID_CHARACTER: + case PP_INVALID_CHARACTER: return "invalid character"; - case INVALID_NUMBER: + case PP_INVALID_NUMBER: return "invalid number"; - case INTEGER_OVERFLOW: + case PP_INTEGER_OVERFLOW: return "integer overflow"; - case FLOAT_OVERFLOW: + case PP_FLOAT_OVERFLOW: return "float overflow"; - case TOKEN_TOO_LONG: + case PP_TOKEN_TOO_LONG: return "token too long"; - case INVALID_EXPRESSION: + case PP_INVALID_EXPRESSION: return "invalid expression"; - case DIVISION_BY_ZERO: + case PP_DIVISION_BY_ZERO: return "division by zero"; - case EOF_IN_COMMENT: + case PP_EOF_IN_COMMENT: return "unexpected end of file found in comment"; - case UNEXPECTED_TOKEN: + case PP_UNEXPECTED_TOKEN: return "unexpected token"; - case DIRECTIVE_INVALID_NAME: + case PP_DIRECTIVE_INVALID_NAME: return "invalid directive name"; - case MACRO_NAME_RESERVED: + case PP_MACRO_NAME_RESERVED: return "macro name is reserved"; - case MACRO_REDEFINED: + case PP_MACRO_REDEFINED: return "macro redefined"; - case MACRO_PREDEFINED_REDEFINED: + case PP_MACRO_PREDEFINED_REDEFINED: return "predefined macro redefined"; - case MACRO_PREDEFINED_UNDEFINED: + case PP_MACRO_PREDEFINED_UNDEFINED: return "predefined macro undefined"; - case MACRO_UNTERMINATED_INVOCATION: + case PP_MACRO_UNTERMINATED_INVOCATION: return "unterminated macro invocation"; - case MACRO_TOO_FEW_ARGS: + case PP_MACRO_TOO_FEW_ARGS: return "Not enough arguments for macro"; - case MACRO_TOO_MANY_ARGS: + case PP_MACRO_TOO_MANY_ARGS: return "Too many arguments for macro"; - case CONDITIONAL_ENDIF_WITHOUT_IF: + case PP_CONDITIONAL_ENDIF_WITHOUT_IF: return "unexpected #endif found without a matching #if"; - case CONDITIONAL_ELSE_WITHOUT_IF: + case PP_CONDITIONAL_ELSE_WITHOUT_IF: return "unexpected #else found without a matching #if"; - case CONDITIONAL_ELSE_AFTER_ELSE: + case PP_CONDITIONAL_ELSE_AFTER_ELSE: return "unexpected #else found after another #else"; - case CONDITIONAL_ELIF_WITHOUT_IF: + case PP_CONDITIONAL_ELIF_WITHOUT_IF: return "unexpected #elif found without a matching #if"; - case CONDITIONAL_ELIF_AFTER_ELSE: + case PP_CONDITIONAL_ELIF_AFTER_ELSE: return "unexpected #elif found after #else"; - case CONDITIONAL_UNTERMINATED: + case PP_CONDITIONAL_UNTERMINATED: return "unexpected end of file found in conditional block"; - case INVALID_EXTENSION_NAME: + case PP_INVALID_EXTENSION_NAME: return "invalid extension name"; - case INVALID_EXTENSION_BEHAVIOR: + case PP_INVALID_EXTENSION_BEHAVIOR: return "invalid extension behavior"; - case INVALID_EXTENSION_DIRECTIVE: + case PP_INVALID_EXTENSION_DIRECTIVE: return "invalid extension directive"; - case INVALID_VERSION_NUMBER: + case PP_INVALID_VERSION_NUMBER: return "invalid version number"; - case INVALID_VERSION_DIRECTIVE: + case PP_INVALID_VERSION_DIRECTIVE: return "invalid version directive"; - case VERSION_NOT_FIRST_STATEMENT: + case PP_VERSION_NOT_FIRST_STATEMENT: return "#version directive must occur before anything else, " "except for comments and white space"; - case INVALID_LINE_NUMBER: + case PP_INVALID_LINE_NUMBER: return "invalid line number"; - case INVALID_FILE_NUMBER: + case PP_INVALID_FILE_NUMBER: return "invalid file number"; - case INVALID_LINE_DIRECTIVE: + case PP_INVALID_LINE_DIRECTIVE: return "invalid line directive"; // Errors end. // Warnings begin. - case EOF_IN_DIRECTIVE: + case PP_EOF_IN_DIRECTIVE: return "unexpected end of file found in directive"; - case CONDITIONAL_UNEXPECTED_TOKEN: + case PP_CONDITIONAL_UNEXPECTED_TOKEN: return "unexpected token after conditional expression"; - case UNRECOGNIZED_PRAGMA: + case PP_UNRECOGNIZED_PRAGMA: return "unrecognized pragma"; // Warnings end. default: diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h index 07bc411846..2c8c539137 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h @@ -21,53 +21,53 @@ class Diagnostics public: enum Severity { - ERROR, - WARNING + PP_ERROR, + PP_WARNING }; enum ID { - ERROR_BEGIN, - INTERNAL_ERROR, - OUT_OF_MEMORY, - INVALID_CHARACTER, - INVALID_NUMBER, - INTEGER_OVERFLOW, - FLOAT_OVERFLOW, - TOKEN_TOO_LONG, - INVALID_EXPRESSION, - DIVISION_BY_ZERO, - EOF_IN_COMMENT, - UNEXPECTED_TOKEN, - DIRECTIVE_INVALID_NAME, - MACRO_NAME_RESERVED, - MACRO_REDEFINED, - MACRO_PREDEFINED_REDEFINED, - MACRO_PREDEFINED_UNDEFINED, - MACRO_UNTERMINATED_INVOCATION, - MACRO_TOO_FEW_ARGS, - MACRO_TOO_MANY_ARGS, - CONDITIONAL_ENDIF_WITHOUT_IF, - CONDITIONAL_ELSE_WITHOUT_IF, - CONDITIONAL_ELSE_AFTER_ELSE, - CONDITIONAL_ELIF_WITHOUT_IF, - CONDITIONAL_ELIF_AFTER_ELSE, - CONDITIONAL_UNTERMINATED, - INVALID_EXTENSION_NAME, - INVALID_EXTENSION_BEHAVIOR, - INVALID_EXTENSION_DIRECTIVE, - INVALID_VERSION_NUMBER, - INVALID_VERSION_DIRECTIVE, - VERSION_NOT_FIRST_STATEMENT, - INVALID_LINE_NUMBER, - INVALID_FILE_NUMBER, - INVALID_LINE_DIRECTIVE, - ERROR_END, + PP_ERROR_BEGIN, + PP_INTERNAL_ERROR, + PP_OUT_OF_MEMORY, + PP_INVALID_CHARACTER, + PP_INVALID_NUMBER, + PP_INTEGER_OVERFLOW, + PP_FLOAT_OVERFLOW, + PP_TOKEN_TOO_LONG, + PP_INVALID_EXPRESSION, + PP_DIVISION_BY_ZERO, + PP_EOF_IN_COMMENT, + PP_UNEXPECTED_TOKEN, + PP_DIRECTIVE_INVALID_NAME, + PP_MACRO_NAME_RESERVED, + PP_MACRO_REDEFINED, + PP_MACRO_PREDEFINED_REDEFINED, + PP_MACRO_PREDEFINED_UNDEFINED, + PP_MACRO_UNTERMINATED_INVOCATION, + PP_MACRO_TOO_FEW_ARGS, + PP_MACRO_TOO_MANY_ARGS, + PP_CONDITIONAL_ENDIF_WITHOUT_IF, + PP_CONDITIONAL_ELSE_WITHOUT_IF, + PP_CONDITIONAL_ELSE_AFTER_ELSE, + PP_CONDITIONAL_ELIF_WITHOUT_IF, + PP_CONDITIONAL_ELIF_AFTER_ELSE, + PP_CONDITIONAL_UNTERMINATED, + PP_INVALID_EXTENSION_NAME, + PP_INVALID_EXTENSION_BEHAVIOR, + PP_INVALID_EXTENSION_DIRECTIVE, + PP_INVALID_VERSION_NUMBER, + PP_INVALID_VERSION_DIRECTIVE, + PP_VERSION_NOT_FIRST_STATEMENT, + PP_INVALID_LINE_NUMBER, + PP_INVALID_FILE_NUMBER, + PP_INVALID_LINE_DIRECTIVE, + PP_ERROR_END, - WARNING_BEGIN, - EOF_IN_DIRECTIVE, - CONDITIONAL_UNEXPECTED_TOKEN, - UNRECOGNIZED_PRAGMA, - WARNING_END + PP_WARNING_BEGIN, + PP_EOF_IN_DIRECTIVE, + PP_CONDITIONAL_UNEXPECTED_TOKEN, + PP_UNRECOGNIZED_PRAGMA, + PP_WARNING_END }; virtual ~Diagnostics(); diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp index 94dfdf513d..ebec79804d 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp @@ -172,7 +172,7 @@ class DefinedParser : public Lexer if (token->type != Token::IDENTIFIER) { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); skipUntilEOD(mLexer, token); return; @@ -185,7 +185,7 @@ class DefinedParser : public Lexer mLexer->lex(token); if (token->type != ')') { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); skipUntilEOD(mLexer, token); return; @@ -233,7 +233,7 @@ void DirectiveParser::lex(Token* token) if (!mConditionalStack.empty()) { const ConditionalBlock& block = mConditionalStack.back(); - mDiagnostics->report(Diagnostics::CONDITIONAL_UNTERMINATED, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNTERMINATED, block.location, block.type); } break; @@ -268,7 +268,7 @@ void DirectiveParser::parseDirective(Token* token) switch(directive) { case DIRECTIVE_NONE: - mDiagnostics->report(Diagnostics::DIRECTIVE_INVALID_NAME, + mDiagnostics->report(Diagnostics::PP_DIRECTIVE_INVALID_NAME, token->location, token->text); skipUntilEOD(mTokenizer, token); break; @@ -319,7 +319,7 @@ void DirectiveParser::parseDirective(Token* token) skipUntilEOD(mTokenizer, token); if (token->type == Token::LAST) { - mDiagnostics->report(Diagnostics::EOF_IN_DIRECTIVE, + mDiagnostics->report(Diagnostics::PP_EOF_IN_DIRECTIVE, token->location, token->text); } } @@ -331,19 +331,19 @@ void DirectiveParser::parseDefine(Token* token) mTokenizer->lex(token); if (token->type != Token::IDENTIFIER) { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); return; } if (isMacroPredefined(token->text, *mMacroSet)) { - mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_REDEFINED, + mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_REDEFINED, token->location, token->text); return; } if (isMacroNameReserved(token->text)) { - mDiagnostics->report(Diagnostics::MACRO_NAME_RESERVED, + mDiagnostics->report(Diagnostics::PP_MACRO_NAME_RESERVED, token->location, token->text); return; } @@ -368,7 +368,7 @@ void DirectiveParser::parseDefine(Token* token) if (token->type != ')') { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); return; @@ -396,7 +396,7 @@ void DirectiveParser::parseDefine(Token* token) MacroSet::const_iterator iter = mMacroSet->find(macro.name); if (iter != mMacroSet->end() && !macro.equals(iter->second)) { - mDiagnostics->report(Diagnostics::MACRO_REDEFINED, + mDiagnostics->report(Diagnostics::PP_MACRO_REDEFINED, token->location, macro.name); return; @@ -411,7 +411,7 @@ void DirectiveParser::parseUndef(Token* token) mTokenizer->lex(token); if (token->type != Token::IDENTIFIER) { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); return; } @@ -421,7 +421,7 @@ void DirectiveParser::parseUndef(Token* token) { if (iter->second.predefined) { - mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_UNDEFINED, + mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED, token->location, token->text); } else @@ -457,7 +457,7 @@ void DirectiveParser::parseElse(Token* token) if (mConditionalStack.empty()) { - mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_WITHOUT_IF, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_WITHOUT_IF, token->location, token->text); skipUntilEOD(mTokenizer, token); return; @@ -472,7 +472,7 @@ void DirectiveParser::parseElse(Token* token) } if (block.foundElseGroup) { - mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_AFTER_ELSE, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_AFTER_ELSE, token->location, token->text); skipUntilEOD(mTokenizer, token); return; @@ -486,7 +486,7 @@ void DirectiveParser::parseElse(Token* token) mTokenizer->lex(token); if (!isEOD(token)) { - mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location, token->text); skipUntilEOD(mTokenizer, token); } @@ -498,7 +498,7 @@ void DirectiveParser::parseElif(Token* token) if (mConditionalStack.empty()) { - mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_WITHOUT_IF, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_WITHOUT_IF, token->location, token->text); skipUntilEOD(mTokenizer, token); return; @@ -513,7 +513,7 @@ void DirectiveParser::parseElif(Token* token) } if (block.foundElseGroup) { - mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_AFTER_ELSE, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_AFTER_ELSE, token->location, token->text); skipUntilEOD(mTokenizer, token); return; @@ -538,7 +538,7 @@ void DirectiveParser::parseEndif(Token* token) if (mConditionalStack.empty()) { - mDiagnostics->report(Diagnostics::CONDITIONAL_ENDIF_WITHOUT_IF, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ENDIF_WITHOUT_IF, token->location, token->text); skipUntilEOD(mTokenizer, token); return; @@ -550,7 +550,7 @@ void DirectiveParser::parseEndif(Token* token) mTokenizer->lex(token); if (!isEOD(token)) { - mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location, token->text); skipUntilEOD(mTokenizer, token); } @@ -618,7 +618,7 @@ void DirectiveParser::parsePragma(Token* token) (state == RIGHT_PAREN + 1)); // With value. if (!valid) { - mDiagnostics->report(Diagnostics::UNRECOGNIZED_PRAGMA, + mDiagnostics->report(Diagnostics::PP_UNRECOGNIZED_PRAGMA, token->location, name); } else if (state > PRAGMA_NAME) // Do not notify for empty pragma. @@ -650,7 +650,7 @@ void DirectiveParser::parseExtension(Token* token) case EXT_NAME: if (valid && (token->type != Token::IDENTIFIER)) { - mDiagnostics->report(Diagnostics::INVALID_EXTENSION_NAME, + mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_NAME, token->location, token->text); valid = false; } @@ -659,7 +659,7 @@ void DirectiveParser::parseExtension(Token* token) case COLON: if (valid && (token->type != ':')) { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); valid = false; } @@ -667,7 +667,7 @@ void DirectiveParser::parseExtension(Token* token) case EXT_BEHAVIOR: if (valid && (token->type != Token::IDENTIFIER)) { - mDiagnostics->report(Diagnostics::INVALID_EXTENSION_BEHAVIOR, + mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_BEHAVIOR, token->location, token->text); valid = false; } @@ -676,7 +676,7 @@ void DirectiveParser::parseExtension(Token* token) default: if (valid) { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); valid = false; } @@ -686,7 +686,7 @@ void DirectiveParser::parseExtension(Token* token) } if (valid && (state != EXT_BEHAVIOR + 1)) { - mDiagnostics->report(Diagnostics::INVALID_EXTENSION_DIRECTIVE, + mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_DIRECTIVE, token->location, token->text); valid = false; } @@ -700,7 +700,7 @@ void DirectiveParser::parseVersion(Token* token) if (mPastFirstStatement) { - mDiagnostics->report(Diagnostics::VERSION_NOT_FIRST_STATEMENT, + mDiagnostics->report(Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT, token->location, token->text); skipUntilEOD(mTokenizer, token); return; @@ -723,13 +723,13 @@ void DirectiveParser::parseVersion(Token* token) case VERSION_NUMBER: if (valid && (token->type != Token::CONST_INT)) { - mDiagnostics->report(Diagnostics::INVALID_VERSION_NUMBER, + mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_NUMBER, token->location, token->text); valid = false; } if (valid && !token->iValue(&version)) { - mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, + mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW, token->location, token->text); valid = false; } @@ -737,7 +737,7 @@ void DirectiveParser::parseVersion(Token* token) default: if (valid) { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); valid = false; } @@ -747,7 +747,7 @@ void DirectiveParser::parseVersion(Token* token) } if (valid && (state != VERSION_NUMBER + 1)) { - mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE, + mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE, token->location, token->text); valid = false; } @@ -778,13 +778,13 @@ void DirectiveParser::parseLine(Token* token) case LINE_NUMBER: if (valid && (token->type != Token::CONST_INT)) { - mDiagnostics->report(Diagnostics::INVALID_LINE_NUMBER, + mDiagnostics->report(Diagnostics::PP_INVALID_LINE_NUMBER, token->location, token->text); valid = false; } if (valid && !token->iValue(&line)) { - mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, + mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW, token->location, token->text); valid = false; } @@ -792,13 +792,13 @@ void DirectiveParser::parseLine(Token* token) case FILE_NUMBER: if (valid && (token->type != Token::CONST_INT)) { - mDiagnostics->report(Diagnostics::INVALID_FILE_NUMBER, + mDiagnostics->report(Diagnostics::PP_INVALID_FILE_NUMBER, token->location, token->text); valid = false; } if (valid && !token->iValue(&file)) { - mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, + mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW, token->location, token->text); valid = false; } @@ -806,7 +806,7 @@ void DirectiveParser::parseLine(Token* token) default: if (valid) { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); valid = false; } @@ -817,7 +817,7 @@ void DirectiveParser::parseLine(Token* token) if (valid && (state != FILE_NUMBER) && (state != FILE_NUMBER + 1)) { - mDiagnostics->report(Diagnostics::INVALID_LINE_DIRECTIVE, + mDiagnostics->report(Diagnostics::PP_INVALID_LINE_DIRECTIVE, token->location, token->text); valid = false; } @@ -893,7 +893,7 @@ int DirectiveParser::parseExpressionIf(Token* token) // Warn if there are tokens after #if expression. if (!isEOD(token)) { - mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location, token->text); skipUntilEOD(mTokenizer, token); } @@ -909,7 +909,7 @@ int DirectiveParser::parseExpressionIfdef(Token* token) mTokenizer->lex(token); if (token->type != Token::IDENTIFIER) { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); skipUntilEOD(mTokenizer, token); return 0; @@ -922,7 +922,7 @@ int DirectiveParser::parseExpressionIfdef(Token* token) mTokenizer->lex(token); if (!isEOD(token)) { - mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location, token->text); skipUntilEOD(mTokenizer, token); } diff --git a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y index b6d3143e60..9fa0f0bf80 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y +++ b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y @@ -33,6 +33,12 @@ WHICH GENERATES THE GLSL ES preprocessor expression parser. #include "ExpressionParser.h" +#if defined(_MSC_VER) +#include +#else +#include +#endif + #include #include @@ -146,7 +152,7 @@ expression std::ostringstream stream; stream << $1 << " % " << $3; std::string text = stream.str(); - context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO, + context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO, context->token->location, text.c_str()); YYABORT; @@ -159,7 +165,7 @@ expression std::ostringstream stream; stream << $1 << " / " << $3; std::string text = stream.str(); - context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO, + context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO, context->token->location, text.c_str()); YYABORT; @@ -201,7 +207,7 @@ int yylex(YYSTYPE* lvalp, Context* context) unsigned int val = 0; if (!token->uValue(&val)) { - context->diagnostics->report(pp::Diagnostics::INTEGER_OVERFLOW, + context->diagnostics->report(pp::Diagnostics::PP_INTEGER_OVERFLOW, token->location, token->text); } *lvalp = static_cast(val); @@ -242,7 +248,7 @@ int yylex(YYSTYPE* lvalp, Context* context) void yyerror(Context* context, const char* reason) { - context->diagnostics->report(pp::Diagnostics::INVALID_EXPRESSION, + context->diagnostics->report(pp::Diagnostics::PP_INVALID_EXPRESSION, context->token->location, reason); } @@ -270,12 +276,12 @@ bool ExpressionParser::parse(Token* token, int* result) break; case 2: - mDiagnostics->report(Diagnostics::OUT_OF_MEMORY, token->location, ""); + mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token->location, ""); break; default: assert(false); - mDiagnostics->report(Diagnostics::INTERNAL_ERROR, token->location, ""); + mDiagnostics->report(Diagnostics::PP_INTERNAL_ERROR, token->location, ""); break; } diff --git a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp index 1116c516ff..b789260af9 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp @@ -254,7 +254,7 @@ bool MacroExpander::collectMacroArgs(const Macro& macro, if (token.type == Token::LAST) { - mDiagnostics->report(Diagnostics::MACRO_UNTERMINATED_INVOCATION, + mDiagnostics->report(Diagnostics::PP_MACRO_UNTERMINATED_INVOCATION, identifier.location, identifier.text); // Do not lose EOF token. ungetToken(token); @@ -302,8 +302,8 @@ bool MacroExpander::collectMacroArgs(const Macro& macro, if (args->size() != params.size()) { Diagnostics::ID id = args->size() < macro.parameters.size() ? - Diagnostics::MACRO_TOO_FEW_ARGS : - Diagnostics::MACRO_TOO_MANY_ARGS; + Diagnostics::PP_MACRO_TOO_FEW_ARGS : + Diagnostics::PP_MACRO_TOO_MANY_ARGS; mDiagnostics->report(id, identifier.location, identifier.text); return false; } diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp index b615c85dce..580ffba459 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp @@ -101,11 +101,11 @@ void Preprocessor::lex(Token* token) assert(false); break; case Token::PP_NUMBER: - mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER, + mImpl->diagnostics->report(Diagnostics::PP_INVALID_NUMBER, token->location, token->text); break; case Token::PP_OTHER: - mImpl->diagnostics->report(Diagnostics::INVALID_CHARACTER, + mImpl->diagnostics->report(Diagnostics::PP_INVALID_CHARACTER, token->location, token->text); break; default: diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l index 01f0177b6c..f1380b26b7 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l +++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l @@ -256,7 +256,7 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".") if (YY_START == COMMENT) { - yyextra->diagnostics->report(pp::Diagnostics::EOF_IN_COMMENT, + yyextra->diagnostics->report(pp::Diagnostics::PP_EOF_IN_COMMENT, pp::SourceLocation(yyfileno, yylineno), ""); } @@ -304,7 +304,7 @@ void Tokenizer::lex(Token* token) token->type = yylex(&token->text, &token->location, mHandle); if (token->text.size() > mMaxTokenLength) { - mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG, + mContext.diagnostics->report(Diagnostics::PP_TOKEN_TOO_LONG, token->location, token->text); token->text.erase(mMaxTokenLength); } diff --git a/src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.cpp b/src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.cpp deleted file mode 100644 index 538b731b8e..0000000000 --- a/src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/InfoSink.h" -#include "compiler/ParseHelper.h" -#include "compiler/depgraph/DependencyGraphOutput.h" -#include "compiler/timing/RestrictFragmentShaderTiming.h" - -RestrictFragmentShaderTiming::RestrictFragmentShaderTiming(TInfoSinkBase& sink) - : mSink(sink) - , mNumErrors(0) -{ - // Sampling ops found only in fragment shaders. - mSamplingOps.insert("texture2D(s21;vf2;f1;"); - mSamplingOps.insert("texture2DProj(s21;vf3;f1;"); - mSamplingOps.insert("texture2DProj(s21;vf4;f1;"); - mSamplingOps.insert("textureCube(sC1;vf3;f1;"); - // Sampling ops found in both vertex and fragment shaders. - mSamplingOps.insert("texture2D(s21;vf2;"); - mSamplingOps.insert("texture2DProj(s21;vf3;"); - mSamplingOps.insert("texture2DProj(s21;vf4;"); - mSamplingOps.insert("textureCube(sC1;vf3;"); - // Sampling ops provided by OES_EGL_image_external. - mSamplingOps.insert("texture2D(1;vf2;"); - mSamplingOps.insert("texture2DProj(1;vf3;"); - mSamplingOps.insert("texture2DProj(1;vf4;"); - // Sampling ops provided by ARB_texture_rectangle. - mSamplingOps.insert("texture2DRect(1;vf2;"); - mSamplingOps.insert("texture2DRectProj(1;vf3;"); - mSamplingOps.insert("texture2DRectProj(1;vf4;"); -} - -// FIXME(mvujovic): We do not know if the execution time of built-in operations like sin, pow, etc. -// can vary based on the value of the input arguments. If so, we should restrict those as well. -void RestrictFragmentShaderTiming::enforceRestrictions(const TDependencyGraph& graph) -{ - mNumErrors = 0; - - // FIXME(mvujovic): The dependency graph does not support user defined function calls right now, - // so we generate errors for them. - validateUserDefinedFunctionCallUsage(graph); - - // Starting from each sampler, traverse the dependency graph and generate an error each time we - // hit a node where sampler dependent values are not allowed. - for (TGraphSymbolVector::const_iterator iter = graph.beginSamplerSymbols(); - iter != graph.endSamplerSymbols(); - ++iter) - { - TGraphSymbol* samplerSymbol = *iter; - clearVisited(); - samplerSymbol->traverse(this); - } -} - -void RestrictFragmentShaderTiming::validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph) -{ - for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls(); - iter != graph.endUserDefinedFunctionCalls(); - ++iter) - { - TGraphFunctionCall* functionCall = *iter; - beginError(functionCall->getIntermFunctionCall()); - mSink << "A call to a user defined function is not permitted.\n"; - } -} - -void RestrictFragmentShaderTiming::beginError(const TIntermNode* node) -{ - ++mNumErrors; - mSink.prefix(EPrefixError); - mSink.location(node->getLine()); -} - -bool RestrictFragmentShaderTiming::isSamplingOp(const TIntermAggregate* intermFunctionCall) const -{ - return !intermFunctionCall->isUserDefined() && - mSamplingOps.find(intermFunctionCall->getName()) != mSamplingOps.end(); -} - -void RestrictFragmentShaderTiming::visitArgument(TGraphArgument* parameter) -{ - // Texture cache access time might leak sensitive information. - // Thus, we restrict sampler dependent values from affecting the coordinate or LOD bias of a - // sampling operation. - if (isSamplingOp(parameter->getIntermFunctionCall())) { - switch (parameter->getArgumentNumber()) { - case 1: - // Second argument (coord) - beginError(parameter->getIntermFunctionCall()); - mSink << "An expression dependent on a sampler is not permitted to be the" - << " coordinate argument of a sampling operation.\n"; - break; - case 2: - // Third argument (bias) - beginError(parameter->getIntermFunctionCall()); - mSink << "An expression dependent on a sampler is not permitted to be the" - << " bias argument of a sampling operation.\n"; - break; - default: - // First argument (sampler) - break; - } - } -} - -void RestrictFragmentShaderTiming::visitSelection(TGraphSelection* selection) -{ - beginError(selection->getIntermSelection()); - mSink << "An expression dependent on a sampler is not permitted in a conditional statement.\n"; -} - -void RestrictFragmentShaderTiming::visitLoop(TGraphLoop* loop) -{ - beginError(loop->getIntermLoop()); - mSink << "An expression dependent on a sampler is not permitted in a loop condition.\n"; -} - -void RestrictFragmentShaderTiming::visitLogicalOp(TGraphLogicalOp* logicalOp) -{ - beginError(logicalOp->getIntermLogicalOp()); - mSink << "An expression dependent on a sampler is not permitted on the left hand side of a logical " - << logicalOp->getOpString() - << " operator.\n"; -} diff --git a/src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.h b/src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.h deleted file mode 100644 index 899165ca28..0000000000 --- a/src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ -#define COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ - -#include "GLSLANG/ShaderLang.h" - -#include "compiler/intermediate.h" -#include "compiler/depgraph/DependencyGraph.h" - -class TInfoSinkBase; - -class RestrictFragmentShaderTiming : TDependencyGraphTraverser { -public: - RestrictFragmentShaderTiming(TInfoSinkBase& sink); - void enforceRestrictions(const TDependencyGraph& graph); - int numErrors() const { return mNumErrors; } - - virtual void visitArgument(TGraphArgument* parameter); - virtual void visitSelection(TGraphSelection* selection); - virtual void visitLoop(TGraphLoop* loop); - virtual void visitLogicalOp(TGraphLogicalOp* logicalOp); - -private: - void beginError(const TIntermNode* node); - void validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph); - bool isSamplingOp(const TIntermAggregate* intermFunctionCall) const; - - TInfoSinkBase& mSink; - int mNumErrors; - - typedef std::set StringSet; - StringSet mSamplingOps; -}; - -#endif // COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ diff --git a/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp b/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp deleted file mode 100644 index 355eb62d65..0000000000 --- a/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/timing/RestrictVertexShaderTiming.h" - -void RestrictVertexShaderTiming::visitSymbol(TIntermSymbol* node) -{ - if (IsSampler(node->getBasicType())) { - ++mNumErrors; - mSink.message(EPrefixError, - node->getLine(), - "Samplers are not permitted in vertex shaders"); - } -} diff --git a/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.h b/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.h deleted file mode 100644 index 19a05fa68b..0000000000 --- a/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ -#define COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ - -#include "GLSLANG/ShaderLang.h" - -#include "compiler/intermediate.h" -#include "compiler/InfoSink.h" - -class TInfoSinkBase; - -class RestrictVertexShaderTiming : public TIntermTraverser { -public: - RestrictVertexShaderTiming(TInfoSinkBase& sink) - : TIntermTraverser(true, false, false) - , mSink(sink) - , mNumErrors(0) {} - - void enforceRestrictions(TIntermNode* root) { root->traverse(this); } - int numErrors() { return mNumErrors; } - - virtual void visitSymbol(TIntermSymbol*); -private: - TInfoSinkBase& mSink; - int mNumErrors; -}; - -#endif // COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h new file mode 100644 index 0000000000..7bdaf14983 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h @@ -0,0 +1,149 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _BASICTYPES_INCLUDED_ +#define _BASICTYPES_INCLUDED_ + +// +// Precision qualifiers +// +enum TPrecision +{ + // These need to be kept sorted + EbpUndefined, + EbpLow, + EbpMedium, + EbpHigh +}; + +inline const char* getPrecisionString(TPrecision p) +{ + switch(p) + { + case EbpHigh: return "highp"; break; + case EbpMedium: return "mediump"; break; + case EbpLow: return "lowp"; break; + default: return "mediump"; break; // Safest fallback + } +} + +// +// Basic type. Arrays, vectors, etc., are orthogonal to this. +// +enum TBasicType +{ + EbtVoid, + EbtFloat, + EbtInt, + EbtBool, + EbtGuardSamplerBegin, // non type: see implementation of IsSampler() + EbtSampler2D, + EbtSamplerCube, + EbtSamplerExternalOES, // Only valid if OES_EGL_image_external exists. + EbtSampler2DRect, // Only valid if GL_ARB_texture_rectangle exists. + EbtGuardSamplerEnd, // non type: see implementation of IsSampler() + EbtStruct, + EbtAddress, // should be deprecated?? + EbtInvariant // used as a type when qualifying a previously declared variable as being invariant +}; + +inline const char* getBasicString(TBasicType t) +{ + switch (t) + { + case EbtVoid: return "void"; break; + case EbtFloat: return "float"; break; + case EbtInt: return "int"; break; + case EbtBool: return "bool"; break; + case EbtSampler2D: return "sampler2D"; break; + case EbtSamplerCube: return "samplerCube"; break; + case EbtSamplerExternalOES: return "samplerExternalOES"; break; + case EbtSampler2DRect: return "sampler2DRect"; break; + case EbtStruct: return "structure"; break; + default: return "unknown type"; + } +} + +inline bool IsSampler(TBasicType type) +{ + return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd; +} + +// +// Qualifiers and built-ins. These are mainly used to see what can be read +// or written, and by the machine dependent translator to know which registers +// to allocate variables in. Since built-ins tend to go to different registers +// than varying or uniform, it makes sense they are peers, not sub-classes. +// +enum TQualifier +{ + EvqTemporary, // For temporaries (within a function), read/write + EvqGlobal, // For globals read/write + EvqInternal, // For internal use, not visible to the user + EvqConst, // User defined constants and non-output parameters in functions + EvqAttribute, // Readonly + EvqVaryingIn, // readonly, fragment shaders only + EvqVaryingOut, // vertex shaders only read/write + EvqInvariantVaryingIn, // readonly, fragment shaders only + EvqInvariantVaryingOut, // vertex shaders only read/write + EvqUniform, // Readonly, vertex and fragment + + // parameters + EvqIn, + EvqOut, + EvqInOut, + EvqConstReadOnly, + + // built-ins written by vertex shader + EvqPosition, + EvqPointSize, + + // built-ins read by fragment shader + EvqFragCoord, + EvqFrontFacing, + EvqPointCoord, + + // built-ins written by fragment shader + EvqFragColor, + EvqFragData, + EvqFragDepth, + + // end of list + EvqLast +}; + +// +// This is just for debug print out, carried along with the definitions above. +// +inline const char* getQualifierString(TQualifier q) +{ + switch(q) + { + case EvqTemporary: return "Temporary"; break; + case EvqGlobal: return "Global"; break; + case EvqConst: return "const"; break; + case EvqConstReadOnly: return "const"; break; + case EvqAttribute: return "attribute"; break; + case EvqVaryingIn: return "varying"; break; + case EvqVaryingOut: return "varying"; break; + case EvqInvariantVaryingIn: return "invariant varying"; break; + case EvqInvariantVaryingOut:return "invariant varying"; break; + case EvqUniform: return "uniform"; break; + case EvqIn: return "in"; break; + case EvqOut: return "out"; break; + case EvqInOut: return "inout"; break; + case EvqPosition: return "Position"; break; + case EvqPointSize: return "PointSize"; break; + case EvqFragCoord: return "FragCoord"; break; + case EvqFrontFacing: return "FrontFacing"; break; + case EvqFragColor: return "FragColor"; break; + case EvqFragData: return "FragData"; break; + case EvqFragDepth: return "FragDepth"; break; + default: return "unknown qualifier"; + } +} + +#endif // _BASICTYPES_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp new file mode 100644 index 0000000000..92b71c6bdb --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp @@ -0,0 +1,406 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/BuiltInFunctionEmulator.h" + +#include "compiler/translator/SymbolTable.h" + +namespace { + +// we use macros here instead of function definitions to work around more GLSL +// compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are +// problematic because if the argument has side-effects they will be repeatedly +// evaluated. This is unlikely to show up in real shaders, but is something to +// consider. +const char* kFunctionEmulationVertexSource[] = { + "#error no emulation for cos(float)", + "#error no emulation for cos(vec2)", + "#error no emulation for cos(vec3)", + "#error no emulation for cos(vec4)", + + "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))", + "#error no emulation for distance(vec2, vec2)", + "#error no emulation for distance(vec3, vec3)", + "#error no emulation for distance(vec4, vec4)", + + "#define webgl_dot_emu(x, y) ((x) * (y))", + "#error no emulation for dot(vec2, vec2)", + "#error no emulation for dot(vec3, vec3)", + "#error no emulation for dot(vec4, vec4)", + + "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", + "#error no emulation for length(vec2)", + "#error no emulation for length(vec3)", + "#error no emulation for length(vec4)", + + "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", + "#error no emulation for normalize(vec2)", + "#error no emulation for normalize(vec3)", + "#error no emulation for normalize(vec4)", + + "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))", + "#error no emulation for reflect(vec2, vec2)", + "#error no emulation for reflect(vec3, vec3)", + "#error no emulation for reflect(vec4, vec4)" +}; + +const char* kFunctionEmulationFragmentSource[] = { + "webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }", + "webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }", + "webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }", + "webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }", + + "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))", + "#error no emulation for distance(vec2, vec2)", + "#error no emulation for distance(vec3, vec3)", + "#error no emulation for distance(vec4, vec4)", + + "#define webgl_dot_emu(x, y) ((x) * (y))", + "#error no emulation for dot(vec2, vec2)", + "#error no emulation for dot(vec3, vec3)", + "#error no emulation for dot(vec4, vec4)", + + "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", + "#error no emulation for length(vec2)", + "#error no emulation for length(vec3)", + "#error no emulation for length(vec4)", + + "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", + "#error no emulation for normalize(vec2)", + "#error no emulation for normalize(vec3)", + "#error no emulation for normalize(vec4)", + + "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))", + "#error no emulation for reflect(vec2, vec2)", + "#error no emulation for reflect(vec3, vec3)", + "#error no emulation for reflect(vec4, vec4)" +}; + +const bool kFunctionEmulationVertexMask[] = { +#if defined(__APPLE__) + // Work around ATI driver bugs in Mac. + false, // TFunctionCos1 + false, // TFunctionCos2 + false, // TFunctionCos3 + false, // TFunctionCos4 + true, // TFunctionDistance1_1 + false, // TFunctionDistance2_2 + false, // TFunctionDistance3_3 + false, // TFunctionDistance4_4 + true, // TFunctionDot1_1 + false, // TFunctionDot2_2 + false, // TFunctionDot3_3 + false, // TFunctionDot4_4 + true, // TFunctionLength1 + false, // TFunctionLength2 + false, // TFunctionLength3 + false, // TFunctionLength4 + true, // TFunctionNormalize1 + false, // TFunctionNormalize2 + false, // TFunctionNormalize3 + false, // TFunctionNormalize4 + true, // TFunctionReflect1_1 + false, // TFunctionReflect2_2 + false, // TFunctionReflect3_3 + false, // TFunctionReflect4_4 +#else + // Work around D3D driver bug in Win. + false, // TFunctionCos1 + false, // TFunctionCos2 + false, // TFunctionCos3 + false, // TFunctionCos4 + false, // TFunctionDistance1_1 + false, // TFunctionDistance2_2 + false, // TFunctionDistance3_3 + false, // TFunctionDistance4_4 + false, // TFunctionDot1_1 + false, // TFunctionDot2_2 + false, // TFunctionDot3_3 + false, // TFunctionDot4_4 + false, // TFunctionLength1 + false, // TFunctionLength2 + false, // TFunctionLength3 + false, // TFunctionLength4 + false, // TFunctionNormalize1 + false, // TFunctionNormalize2 + false, // TFunctionNormalize3 + false, // TFunctionNormalize4 + false, // TFunctionReflect1_1 + false, // TFunctionReflect2_2 + false, // TFunctionReflect3_3 + false, // TFunctionReflect4_4 +#endif + false // TFunctionUnknown +}; + +const bool kFunctionEmulationFragmentMask[] = { +#if defined(__APPLE__) + // Work around ATI driver bugs in Mac. + true, // TFunctionCos1 + true, // TFunctionCos2 + true, // TFunctionCos3 + true, // TFunctionCos4 + true, // TFunctionDistance1_1 + false, // TFunctionDistance2_2 + false, // TFunctionDistance3_3 + false, // TFunctionDistance4_4 + true, // TFunctionDot1_1 + false, // TFunctionDot2_2 + false, // TFunctionDot3_3 + false, // TFunctionDot4_4 + true, // TFunctionLength1 + false, // TFunctionLength2 + false, // TFunctionLength3 + false, // TFunctionLength4 + true, // TFunctionNormalize1 + false, // TFunctionNormalize2 + false, // TFunctionNormalize3 + false, // TFunctionNormalize4 + true, // TFunctionReflect1_1 + false, // TFunctionReflect2_2 + false, // TFunctionReflect3_3 + false, // TFunctionReflect4_4 +#else + // Work around D3D driver bug in Win. + false, // TFunctionCos1 + false, // TFunctionCos2 + false, // TFunctionCos3 + false, // TFunctionCos4 + false, // TFunctionDistance1_1 + false, // TFunctionDistance2_2 + false, // TFunctionDistance3_3 + false, // TFunctionDistance4_4 + false, // TFunctionDot1_1 + false, // TFunctionDot2_2 + false, // TFunctionDot3_3 + false, // TFunctionDot4_4 + false, // TFunctionLength1 + false, // TFunctionLength2 + false, // TFunctionLength3 + false, // TFunctionLength4 + false, // TFunctionNormalize1 + false, // TFunctionNormalize2 + false, // TFunctionNormalize3 + false, // TFunctionNormalize4 + false, // TFunctionReflect1_1 + false, // TFunctionReflect2_2 + false, // TFunctionReflect3_3 + false, // TFunctionReflect4_4 +#endif + false // TFunctionUnknown +}; + +class BuiltInFunctionEmulationMarker : public TIntermTraverser { +public: + BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator& emulator) + : mEmulator(emulator) + { + } + + virtual bool visitUnary(Visit visit, TIntermUnary* node) + { + if (visit == PreVisit) { + bool needToEmulate = mEmulator.SetFunctionCalled( + node->getOp(), node->getOperand()->getType()); + if (needToEmulate) + node->setUseEmulatedFunction(); + } + return true; + } + + virtual bool visitAggregate(Visit visit, TIntermAggregate* node) + { + if (visit == PreVisit) { + // Here we handle all the built-in functions instead of the ones we + // currently identified as problematic. + switch (node->getOp()) { + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + case EOpVectorEqual: + case EOpVectorNotEqual: + case EOpMod: + case EOpPow: + case EOpAtan: + case EOpMin: + case EOpMax: + case EOpClamp: + case EOpMix: + case EOpStep: + case EOpSmoothStep: + case EOpDistance: + case EOpDot: + case EOpCross: + case EOpFaceForward: + case EOpReflect: + case EOpRefract: + case EOpMul: + break; + default: + return true; + }; + const TIntermSequence& sequence = node->getSequence(); + // Right now we only handle built-in functions with two parameters. + if (sequence.size() != 2) + return true; + TIntermTyped* param1 = sequence[0]->getAsTyped(); + TIntermTyped* param2 = sequence[1]->getAsTyped(); + if (!param1 || !param2) + return true; + bool needToEmulate = mEmulator.SetFunctionCalled( + node->getOp(), param1->getType(), param2->getType()); + if (needToEmulate) + node->setUseEmulatedFunction(); + } + return true; + } + +private: + BuiltInFunctionEmulator& mEmulator; +}; + +} // anonymous namepsace + +BuiltInFunctionEmulator::BuiltInFunctionEmulator(ShShaderType shaderType) +{ + if (shaderType == SH_FRAGMENT_SHADER) { + mFunctionMask = kFunctionEmulationFragmentMask; + mFunctionSource = kFunctionEmulationFragmentSource; + } else { + mFunctionMask = kFunctionEmulationVertexMask; + mFunctionSource = kFunctionEmulationVertexSource; + } +} + +bool BuiltInFunctionEmulator::SetFunctionCalled( + TOperator op, const TType& param) +{ + TBuiltInFunction function = IdentifyFunction(op, param); + return SetFunctionCalled(function); +} + +bool BuiltInFunctionEmulator::SetFunctionCalled( + TOperator op, const TType& param1, const TType& param2) +{ + TBuiltInFunction function = IdentifyFunction(op, param1, param2); + return SetFunctionCalled(function); +} + +bool BuiltInFunctionEmulator::SetFunctionCalled( + BuiltInFunctionEmulator::TBuiltInFunction function) { + if (function == TFunctionUnknown || mFunctionMask[function] == false) + return false; + for (size_t i = 0; i < mFunctions.size(); ++i) { + if (mFunctions[i] == function) + return true; + } + mFunctions.push_back(function); + return true; +} + +void BuiltInFunctionEmulator::OutputEmulatedFunctionDefinition( + TInfoSinkBase& out, bool withPrecision) const +{ + if (mFunctions.size() == 0) + return; + out << "// BEGIN: Generated code for built-in function emulation\n\n"; + if (withPrecision) { + out << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n" + << "#define webgl_emu_precision highp\n" + << "#else\n" + << "#define webgl_emu_precision mediump\n" + << "#endif\n\n"; + } else { + out << "#define webgl_emu_precision\n\n"; + } + for (size_t i = 0; i < mFunctions.size(); ++i) { + out << mFunctionSource[mFunctions[i]] << "\n\n"; + } + out << "// END: Generated code for built-in function emulation\n\n"; +} + +BuiltInFunctionEmulator::TBuiltInFunction +BuiltInFunctionEmulator::IdentifyFunction( + TOperator op, const TType& param) +{ + if (param.getNominalSize() > 4) + return TFunctionUnknown; + unsigned int function = TFunctionUnknown; + switch (op) { + case EOpCos: + function = TFunctionCos1; + break; + case EOpLength: + function = TFunctionLength1; + break; + case EOpNormalize: + function = TFunctionNormalize1; + break; + default: + break; + } + if (function == TFunctionUnknown) + return TFunctionUnknown; + if (param.isVector()) + function += param.getNominalSize() - 1; + return static_cast(function); +} + +BuiltInFunctionEmulator::TBuiltInFunction +BuiltInFunctionEmulator::IdentifyFunction( + TOperator op, const TType& param1, const TType& param2) +{ + // Right now for all the emulated functions with two parameters, the two + // parameters have the same type. + if (param1.isVector() != param2.isVector() || + param1.getNominalSize() != param2.getNominalSize() || + param1.getNominalSize() > 4) + return TFunctionUnknown; + + unsigned int function = TFunctionUnknown; + switch (op) { + case EOpDistance: + function = TFunctionDistance1_1; + break; + case EOpDot: + function = TFunctionDot1_1; + break; + case EOpReflect: + function = TFunctionReflect1_1; + break; + default: + break; + } + if (function == TFunctionUnknown) + return TFunctionUnknown; + if (param1.isVector()) + function += param1.getNominalSize() - 1; + return static_cast(function); +} + +void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation( + TIntermNode* root) +{ + ASSERT(root); + + BuiltInFunctionEmulationMarker marker(*this); + root->traverse(&marker); +} + +void BuiltInFunctionEmulator::Cleanup() +{ + mFunctions.clear(); +} + +//static +TString BuiltInFunctionEmulator::GetEmulatedFunctionName( + const TString& name) +{ + ASSERT(name[name.length() - 1] == '('); + return "webgl_" + name.substr(0, name.length() - 1) + "_emu("; +} + diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h new file mode 100644 index 0000000000..cfb71a803a --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h @@ -0,0 +1,93 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ +#define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ + +#include "GLSLANG/ShaderLang.h" + +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/intermediate.h" + +// +// This class decides which built-in functions need to be replaced with the +// emulated ones. +// It's only a workaround for OpenGL driver bugs, and isn't needed in general. +// +class BuiltInFunctionEmulator { +public: + BuiltInFunctionEmulator(ShShaderType shaderType); + // Records that a function is called by the shader and might needs to be + // emulated. If the function's group is not in mFunctionGroupFilter, this + // becomes an no-op. + // Returns true if the function call needs to be replaced with an emulated + // one. + bool SetFunctionCalled(TOperator op, const TType& param); + bool SetFunctionCalled( + TOperator op, const TType& param1, const TType& param2); + + // Output function emulation definition. This should be before any other + // shader source. + void OutputEmulatedFunctionDefinition(TInfoSinkBase& out, bool withPrecision) const; + + void MarkBuiltInFunctionsForEmulation(TIntermNode* root); + + void Cleanup(); + + // "name(" becomes "webgl_name_emu(". + static TString GetEmulatedFunctionName(const TString& name); + +private: + // + // Built-in functions. + // + enum TBuiltInFunction { + TFunctionCos1 = 0, // float cos(float); + TFunctionCos2, // vec2 cos(vec2); + TFunctionCos3, // vec3 cos(vec3); + TFunctionCos4, // vec4 cos(vec4); + + TFunctionDistance1_1, // float distance(float, float); + TFunctionDistance2_2, // vec2 distance(vec2, vec2); + TFunctionDistance3_3, // vec3 distance(vec3, vec3); + TFunctionDistance4_4, // vec4 distance(vec4, vec4); + + TFunctionDot1_1, // float dot(float, float); + TFunctionDot2_2, // vec2 dot(vec2, vec2); + TFunctionDot3_3, // vec3 dot(vec3, vec3); + TFunctionDot4_4, // vec4 dot(vec4, vec4); + + TFunctionLength1, // float length(float); + TFunctionLength2, // float length(vec2); + TFunctionLength3, // float length(vec3); + TFunctionLength4, // float length(vec4); + + TFunctionNormalize1, // float normalize(float); + TFunctionNormalize2, // vec2 normalize(vec2); + TFunctionNormalize3, // vec3 normalize(vec3); + TFunctionNormalize4, // vec4 normalize(vec4); + + TFunctionReflect1_1, // float reflect(float, float); + TFunctionReflect2_2, // vec2 reflect(vec2, vec2); + TFunctionReflect3_3, // vec3 reflect(vec3, vec3); + TFunctionReflect4_4, // vec4 reflect(vec4, vec4); + + TFunctionUnknown + }; + + TBuiltInFunction IdentifyFunction(TOperator op, const TType& param); + TBuiltInFunction IdentifyFunction( + TOperator op, const TType& param1, const TType& param2); + + bool SetFunctionCalled(TBuiltInFunction function); + + std::vector mFunctions; + + const bool* mFunctionMask; // a boolean flag for each function. + const char** mFunctionSource; +}; + +#endif // COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp b/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp new file mode 100644 index 0000000000..8f5d129104 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/CodeGen.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. +// + +#include "compiler/translator/TranslatorESSL.h" +#include "compiler/translator/TranslatorGLSL.h" +#include "compiler/translator/TranslatorHLSL.h" + +// +// This function must be provided to create the actual +// compile object used by higher level code. It returns +// a subclass of TCompiler. +// +TCompiler* ConstructCompiler( + ShShaderType type, ShShaderSpec spec, ShShaderOutput output) +{ + switch (output) { + case SH_ESSL_OUTPUT: + return new TranslatorESSL(type, spec); + case SH_GLSL_OUTPUT: + return new TranslatorGLSL(type, spec); + case SH_HLSL9_OUTPUT: + case SH_HLSL11_OUTPUT: + return new TranslatorHLSL(type, spec, output); + default: + return NULL; + } +} + +// +// Delete the compiler made by ConstructCompiler +// +void DeleteCompiler(TCompiler* compiler) +{ + delete compiler; +} diff --git a/src/3rdparty/angle/src/compiler/translator/Common.h b/src/3rdparty/angle/src/compiler/translator/Common.h new file mode 100644 index 0000000000..1e4503e340 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/Common.h @@ -0,0 +1,92 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _COMMON_INCLUDED_ +#define _COMMON_INCLUDED_ + +#include +#include +#include +#include +#include +#include + +#include "compiler/translator/PoolAlloc.h" +#include "compiler/translator/compilerdebug.h" +#include "common/angleutils.h" + +struct TSourceLoc { + int first_file; + int first_line; + int last_file; + int last_line; +}; + +// +// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. +// +#define POOL_ALLOCATOR_NEW_DELETE() \ + void* operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ + void* operator new(size_t, void *_Where) { return (_Where); } \ + void operator delete(void*) { } \ + void operator delete(void *, void *) { } \ + void* operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ + void* operator new[](size_t, void *_Where) { return (_Where); } \ + void operator delete[](void*) { } \ + void operator delete[](void *, void *) { } + +// +// Pool version of string. +// +typedef pool_allocator TStringAllocator; +typedef std::basic_string , TStringAllocator> TString; +typedef std::basic_ostringstream, TStringAllocator> TStringStream; +inline TString* NewPoolTString(const char* s) +{ + void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TString)); + return new(memory) TString(s); +} + +// +// Persistent string memory. Should only be used for strings that survive +// across compiles. +// +#define TPersistString std::string +#define TPersistStringStream std::ostringstream + +// +// Pool allocator versions of vectors, lists, and maps +// +template class TVector : public std::vector > { +public: + typedef typename std::vector >::size_type size_type; + TVector() : std::vector >() {} + TVector(const pool_allocator& a) : std::vector >(a) {} + TVector(size_type i): std::vector >(i) {} +}; + +template > +class TMap : public std::map > > { +public: + typedef pool_allocator > tAllocator; + + TMap() : std::map() {} + // use correct two-stage name lookup supported in gcc 3.4 and above + TMap(const tAllocator& a) : std::map(std::map::key_compare(), a) {} +}; + +// Integer to TString conversion +template +inline TString str(T i) +{ + ASSERT(std::numeric_limits::is_integer); + char buffer[((8 * sizeof(T)) / 3) + 3]; + const char *formatStr = std::numeric_limits::is_signed ? "%d" : "%u"; + snprintf(buffer, sizeof(buffer), formatStr, i); + return buffer; +} + +#endif // _COMMON_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp new file mode 100644 index 0000000000..eb7465e35c --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp @@ -0,0 +1,527 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/DetectCallDepth.h" +#include "compiler/translator/ForLoopUnroll.h" +#include "compiler/translator/Initialize.h" +#include "compiler/translator/InitializeParseContext.h" +#include "compiler/translator/InitializeVariables.h" +#include "compiler/translator/MapLongVariableNames.h" +#include "compiler/translator/ParseContext.h" +#include "compiler/translator/RenameFunction.h" +#include "compiler/translator/ShHandle.h" +#include "compiler/translator/UnfoldShortCircuitAST.h" +#include "compiler/translator/ValidateLimitations.h" +#include "compiler/translator/VariablePacker.h" +#include "compiler/translator/depgraph/DependencyGraph.h" +#include "compiler/translator/depgraph/DependencyGraphOutput.h" +#include "compiler/translator/timing/RestrictFragmentShaderTiming.h" +#include "compiler/translator/timing/RestrictVertexShaderTiming.h" +#include "third_party/compiler/ArrayBoundsClamper.h" + +bool isWebGLBasedSpec(ShShaderSpec spec) +{ + return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC; +} + +namespace { +class TScopedPoolAllocator +{ + public: + TScopedPoolAllocator(TPoolAllocator* allocator) : mAllocator(allocator) + { + mAllocator->push(); + SetGlobalPoolAllocator(mAllocator); + } + ~TScopedPoolAllocator() + { + SetGlobalPoolAllocator(NULL); + mAllocator->pop(); + } + + private: + TPoolAllocator* mAllocator; +}; + +class TScopedSymbolTableLevel +{ + public: + TScopedSymbolTableLevel(TSymbolTable* table) : mTable(table) + { + ASSERT(mTable->atBuiltInLevel()); + mTable->push(); + } + ~TScopedSymbolTableLevel() + { + while (!mTable->atBuiltInLevel()) + mTable->pop(); + } + + private: + TSymbolTable* mTable; +}; +} // namespace + +TShHandleBase::TShHandleBase() +{ + allocator.push(); + SetGlobalPoolAllocator(&allocator); +} + +TShHandleBase::~TShHandleBase() +{ + SetGlobalPoolAllocator(NULL); + allocator.popAll(); +} + +TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec) + : shaderType(type), + shaderSpec(spec), + maxUniformVectors(0), + maxExpressionComplexity(0), + maxCallStackDepth(0), + fragmentPrecisionHigh(false), + clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC), + builtInFunctionEmulator(type) +{ + longNameMap = LongNameMap::GetInstance(); +} + +TCompiler::~TCompiler() +{ + ASSERT(longNameMap); + longNameMap->Release(); +} + +bool TCompiler::Init(const ShBuiltInResources& resources) +{ + maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ? + resources.MaxVertexUniformVectors : + resources.MaxFragmentUniformVectors; + maxExpressionComplexity = resources.MaxExpressionComplexity; + maxCallStackDepth = resources.MaxCallStackDepth; + + SetGlobalPoolAllocator(&allocator); + + // Generate built-in symbol table. + if (!InitBuiltInSymbolTable(resources)) + return false; + InitExtensionBehavior(resources, extensionBehavior); + fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1; + + arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy); + clampingStrategy = resources.ArrayIndexClampingStrategy; + + hashFunction = resources.HashFunction; + + return true; +} + +bool TCompiler::compile(const char* const shaderStrings[], + size_t numStrings, + int compileOptions) +{ + TScopedPoolAllocator scopedAlloc(&allocator); + clearResults(); + + if (numStrings == 0) + return true; + + // If compiling for WebGL, validate loop and indexing as well. + if (isWebGLBasedSpec(shaderSpec)) + compileOptions |= SH_VALIDATE_LOOP_INDEXING; + + // First string is path of source file if flag is set. The actual source follows. + const char* sourcePath = NULL; + size_t firstSource = 0; + if (compileOptions & SH_SOURCE_PATH) + { + sourcePath = shaderStrings[0]; + ++firstSource; + } + + TIntermediate intermediate(infoSink); + TParseContext parseContext(symbolTable, extensionBehavior, intermediate, + shaderType, shaderSpec, compileOptions, true, + sourcePath, infoSink); + parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh; + SetGlobalParseContext(&parseContext); + + // We preserve symbols at the built-in level from compile-to-compile. + // Start pushing the user-defined symbols at global level. + TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable); + + // Parse shader. + bool success = + (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) && + (parseContext.treeRoot != NULL); + if (success) + { + TIntermNode* root = parseContext.treeRoot; + success = intermediate.postProcess(root); + + if (success) + success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0); + + if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING)) + success = validateLimitations(root); + + if (success && (compileOptions & SH_TIMING_RESTRICTIONS)) + success = enforceTimingRestrictions(root, (compileOptions & SH_DEPENDENCY_GRAPH) != 0); + + if (success && shaderSpec == SH_CSS_SHADERS_SPEC) + rewriteCSSShader(root); + + // Unroll for-loop markup needs to happen after validateLimitations pass. + if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX)) + ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(root); + + // Built-in function emulation needs to happen after validateLimitations pass. + if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS)) + builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root); + + // Clamping uniform array bounds needs to happen after validateLimitations pass. + if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)) + arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root); + + // Disallow expressions deemed too complex. + if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY)) + success = limitExpressionComplexity(root); + + // Call mapLongVariableNames() before collectAttribsUniforms() so in + // collectAttribsUniforms() we already have the mapped symbol names and + // we could composite mapped and original variable names. + // Also, if we hash all the names, then no need to do this for long names. + if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL) + mapLongVariableNames(root); + + if (success && shaderType == SH_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION)) + initializeGLPosition(root); + + if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT)) + { + UnfoldShortCircuitAST unfoldShortCircuit; + root->traverse(&unfoldShortCircuit); + unfoldShortCircuit.updateTree(); + } + + if (success && (compileOptions & SH_VARIABLES)) + { + collectVariables(root); + if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) + { + success = enforcePackingRestrictions(); + if (!success) + { + infoSink.info.prefix(EPrefixError); + infoSink.info << "too many uniforms"; + } + } + if (success && shaderType == SH_VERTEX_SHADER && + (compileOptions & SH_INIT_VARYINGS_WITHOUT_STATIC_USE)) + initializeVaryingsWithoutStaticUse(root); + } + + if (success && (compileOptions & SH_INTERMEDIATE_TREE)) + intermediate.outputTree(root); + + if (success && (compileOptions & SH_OBJECT_CODE)) + translate(root); + } + + // Cleanup memory. + intermediate.remove(parseContext.treeRoot); + + return success; +} + +bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources) +{ + compileResources = resources; + + assert(symbolTable.isEmpty()); + symbolTable.push(); + + TPublicType integer; + integer.type = EbtInt; + integer.size = 1; + integer.matrix = false; + integer.array = false; + + TPublicType floatingPoint; + floatingPoint.type = EbtFloat; + floatingPoint.size = 1; + floatingPoint.matrix = false; + floatingPoint.array = false; + + TPublicType sampler; + sampler.size = 1; + sampler.matrix = false; + sampler.array = false; + + switch(shaderType) + { + case SH_FRAGMENT_SHADER: + symbolTable.setDefaultPrecision(integer, EbpMedium); + break; + case SH_VERTEX_SHADER: + symbolTable.setDefaultPrecision(integer, EbpHigh); + symbolTable.setDefaultPrecision(floatingPoint, EbpHigh); + break; + default: + assert(false && "Language not supported"); + } + // We set defaults for all the sampler types, even those that are + // only available if an extension exists. + for (int samplerType = EbtGuardSamplerBegin + 1; + samplerType < EbtGuardSamplerEnd; ++samplerType) + { + sampler.type = static_cast(samplerType); + symbolTable.setDefaultPrecision(sampler, EbpLow); + } + + InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable); + + IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable); + + return true; +} + +void TCompiler::clearResults() +{ + arrayBoundsClamper.Cleanup(); + infoSink.info.erase(); + infoSink.obj.erase(); + infoSink.debug.erase(); + + attribs.clear(); + uniforms.clear(); + varyings.clear(); + + builtInFunctionEmulator.Cleanup(); + + nameMap.clear(); +} + +bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth) +{ + DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth); + root->traverse(&detect); + switch (detect.detectCallDepth()) + { + case DetectCallDepth::kErrorNone: + return true; + case DetectCallDepth::kErrorMissingMain: + infoSink.info.prefix(EPrefixError); + infoSink.info << "Missing main()"; + return false; + case DetectCallDepth::kErrorRecursion: + infoSink.info.prefix(EPrefixError); + infoSink.info << "Function recursion detected"; + return false; + case DetectCallDepth::kErrorMaxDepthExceeded: + infoSink.info.prefix(EPrefixError); + infoSink.info << "Function call stack too deep"; + return false; + default: + UNREACHABLE(); + return false; + } +} + +void TCompiler::rewriteCSSShader(TIntermNode* root) +{ + RenameFunction renamer("main(", "css_main("); + root->traverse(&renamer); +} + +bool TCompiler::validateLimitations(TIntermNode* root) +{ + ValidateLimitations validate(shaderType, infoSink.info); + root->traverse(&validate); + return validate.numErrors() == 0; +} + +bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph) +{ + if (shaderSpec != SH_WEBGL_SPEC) + { + infoSink.info << "Timing restrictions must be enforced under the WebGL spec."; + return false; + } + + if (shaderType == SH_FRAGMENT_SHADER) + { + TDependencyGraph graph(root); + + // Output any errors first. + bool success = enforceFragmentShaderTimingRestrictions(graph); + + // Then, output the dependency graph. + if (outputGraph) + { + TDependencyGraphOutput output(infoSink.info); + output.outputAllSpanningTrees(graph); + } + + return success; + } + else + { + return enforceVertexShaderTimingRestrictions(root); + } +} + +bool TCompiler::limitExpressionComplexity(TIntermNode* root) +{ + TIntermTraverser traverser; + root->traverse(&traverser); + TDependencyGraph graph(root); + + for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls(); + iter != graph.endUserDefinedFunctionCalls(); + ++iter) + { + TGraphFunctionCall* samplerSymbol = *iter; + TDependencyGraphTraverser graphTraverser; + samplerSymbol->traverse(&graphTraverser); + } + + if (traverser.getMaxDepth() > maxExpressionComplexity) + { + infoSink.info << "Expression too complex."; + return false; + } + return true; +} + +bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph) +{ + RestrictFragmentShaderTiming restrictor(infoSink.info); + restrictor.enforceRestrictions(graph); + return restrictor.numErrors() == 0; +} + +bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root) +{ + RestrictVertexShaderTiming restrictor(infoSink.info); + restrictor.enforceRestrictions(root); + return restrictor.numErrors() == 0; +} + +void TCompiler::collectVariables(TIntermNode* root) +{ + CollectVariables collect(attribs, uniforms, varyings, hashFunction); + root->traverse(&collect); +} + +bool TCompiler::enforcePackingRestrictions() +{ + VariablePacker packer; + return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, uniforms); +} + +void TCompiler::initializeGLPosition(TIntermNode* root) +{ + InitializeVariables::InitVariableInfoList variables; + InitializeVariables::InitVariableInfo var( + "gl_Position", TType(EbtFloat, EbpUndefined, EvqPosition, 4)); + variables.push_back(var); + InitializeVariables initializer(variables); + root->traverse(&initializer); +} + +void TCompiler::initializeVaryingsWithoutStaticUse(TIntermNode* root) +{ + InitializeVariables::InitVariableInfoList variables; + for (size_t ii = 0; ii < varyings.size(); ++ii) + { + const TVariableInfo& varying = varyings[ii]; + if (varying.staticUse) + continue; + unsigned char size = 0; + bool matrix = false; + switch (varying.type) + { + case SH_FLOAT: + size = 1; + break; + case SH_FLOAT_VEC2: + size = 2; + break; + case SH_FLOAT_VEC3: + size = 3; + break; + case SH_FLOAT_VEC4: + size = 4; + break; + case SH_FLOAT_MAT2: + size = 2; + matrix = true; + break; + case SH_FLOAT_MAT3: + size = 3; + matrix = true; + break; + case SH_FLOAT_MAT4: + size = 4; + matrix = true; + break; + default: + ASSERT(false); + } + TType type(EbtFloat, EbpUndefined, EvqVaryingOut, size, matrix, varying.isArray); + TString name = varying.name.c_str(); + if (varying.isArray) + { + type.setArraySize(varying.size); + name = name.substr(0, name.find_first_of('[')); + } + + InitializeVariables::InitVariableInfo var(name, type); + variables.push_back(var); + } + InitializeVariables initializer(variables); + root->traverse(&initializer); +} + +void TCompiler::mapLongVariableNames(TIntermNode* root) +{ + ASSERT(longNameMap); + MapLongVariableNames map(longNameMap); + root->traverse(&map); +} + +int TCompiler::getMappedNameMaxLength() const +{ + return MAX_SHORTENED_IDENTIFIER_SIZE + 1; +} + +const TExtensionBehavior& TCompiler::getExtensionBehavior() const +{ + return extensionBehavior; +} + +const ShBuiltInResources& TCompiler::getResources() const +{ + return compileResources; +} + +const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const +{ + return arrayBoundsClamper; +} + +ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const +{ + return clampingStrategy; +} + +const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const +{ + return builtInFunctionEmulator; +} diff --git a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h new file mode 100644 index 0000000000..b1e37885f9 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h @@ -0,0 +1,257 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _CONSTANT_UNION_INCLUDED_ +#define _CONSTANT_UNION_INCLUDED_ + +#include + +class ConstantUnion { +public: + POOL_ALLOCATOR_NEW_DELETE(); + ConstantUnion() + { + iConst = 0; + type = EbtVoid; + } + + void setIConst(int i) {iConst = i; type = EbtInt; } + void setFConst(float f) {fConst = f; type = EbtFloat; } + void setBConst(bool b) {bConst = b; type = EbtBool; } + + int getIConst() { return iConst; } + float getFConst() { return fConst; } + bool getBConst() { return bConst; } + int getIConst() const { return iConst; } + float getFConst() const { return fConst; } + bool getBConst() const { return bConst; } + + bool operator==(const int i) const + { + return i == iConst; + } + + bool operator==(const float f) const + { + return f == fConst; + } + + bool operator==(const bool b) const + { + return b == bConst; + } + + bool operator==(const ConstantUnion& constant) const + { + if (constant.type != type) + return false; + + switch (type) { + case EbtInt: + return constant.iConst == iConst; + case EbtFloat: + return constant.fConst == fConst; + case EbtBool: + return constant.bConst == bConst; + default: + return false; + } + } + + bool operator!=(const int i) const + { + return !operator==(i); + } + + bool operator!=(const float f) const + { + return !operator==(f); + } + + bool operator!=(const bool b) const + { + return !operator==(b); + } + + bool operator!=(const ConstantUnion& constant) const + { + return !operator==(constant); + } + + bool operator>(const ConstantUnion& constant) const + { + assert(type == constant.type); + switch (type) { + case EbtInt: + return iConst > constant.iConst; + case EbtFloat: + return fConst > constant.fConst; + default: + return false; // Invalid operation, handled at semantic analysis + } + } + + bool operator<(const ConstantUnion& constant) const + { + assert(type == constant.type); + switch (type) { + case EbtInt: + return iConst < constant.iConst; + case EbtFloat: + return fConst < constant.fConst; + default: + return false; // Invalid operation, handled at semantic analysis + } + } + + ConstantUnion operator+(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst + constant.iConst); break; + case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator-(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst - constant.iConst); break; + case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator*(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst * constant.iConst); break; + case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator%(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst % constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator>>(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator<<(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator&(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator|(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst | constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator^(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator&&(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst && constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + ConstantUnion operator||(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst || constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TBasicType getType() const { return type; } +private: + + union { + int iConst; // used for ivec, scalar ints + bool bConst; // used for bvec, scalar bools + float fConst; // used for vec, mat, scalar floats + } ; + + TBasicType type; +}; + +#endif // _CONSTANT_UNION_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp new file mode 100644 index 0000000000..bfc1d5852f --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp @@ -0,0 +1,185 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/DetectCallDepth.h" +#include "compiler/translator/InfoSink.h" + +DetectCallDepth::FunctionNode::FunctionNode(const TString& fname) + : name(fname), + visit(PreVisit) +{ +} + +const TString& DetectCallDepth::FunctionNode::getName() const +{ + return name; +} + +void DetectCallDepth::FunctionNode::addCallee( + DetectCallDepth::FunctionNode* callee) +{ + for (size_t i = 0; i < callees.size(); ++i) { + if (callees[i] == callee) + return; + } + callees.push_back(callee); +} + +int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDepth, int depth) +{ + ASSERT(visit == PreVisit); + ASSERT(detectCallDepth); + + int maxDepth = depth; + visit = InVisit; + for (size_t i = 0; i < callees.size(); ++i) { + switch (callees[i]->visit) { + case InVisit: + // cycle detected, i.e., recursion detected. + return kInfiniteCallDepth; + case PostVisit: + break; + case PreVisit: { + // Check before we recurse so we don't go too depth + if (detectCallDepth->checkExceedsMaxDepth(depth)) + return depth; + int callDepth = callees[i]->detectCallDepth(detectCallDepth, depth + 1); + // Check after we recurse so we can exit immediately and provide info. + if (detectCallDepth->checkExceedsMaxDepth(callDepth)) { + detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName(); + return callDepth; + } + maxDepth = std::max(callDepth, maxDepth); + break; + } + default: + UNREACHABLE(); + break; + } + } + visit = PostVisit; + return maxDepth; +} + +void DetectCallDepth::FunctionNode::reset() +{ + visit = PreVisit; +} + +DetectCallDepth::DetectCallDepth(TInfoSink& infoSink, bool limitCallStackDepth, int maxCallStackDepth) + : TIntermTraverser(true, false, true, false), + currentFunction(NULL), + infoSink(infoSink), + maxDepth(limitCallStackDepth ? maxCallStackDepth : FunctionNode::kInfiniteCallDepth) +{ +} + +DetectCallDepth::~DetectCallDepth() +{ + for (size_t i = 0; i < functions.size(); ++i) + delete functions[i]; +} + +bool DetectCallDepth::visitAggregate(Visit visit, TIntermAggregate* node) +{ + switch (node->getOp()) + { + case EOpPrototype: + // Function declaration. + // Don't add FunctionNode here because node->getName() is the + // unmangled function name. + break; + case EOpFunction: { + // Function definition. + if (visit == PreVisit) { + currentFunction = findFunctionByName(node->getName()); + if (currentFunction == NULL) { + currentFunction = new FunctionNode(node->getName()); + functions.push_back(currentFunction); + } + } else if (visit == PostVisit) { + currentFunction = NULL; + } + break; + } + case EOpFunctionCall: { + // Function call. + if (visit == PreVisit) { + FunctionNode* func = findFunctionByName(node->getName()); + if (func == NULL) { + func = new FunctionNode(node->getName()); + functions.push_back(func); + } + if (currentFunction) + currentFunction->addCallee(func); + } + break; + } + default: + break; + } + return true; +} + +bool DetectCallDepth::checkExceedsMaxDepth(int depth) +{ + return depth >= maxDepth; +} + +void DetectCallDepth::resetFunctionNodes() +{ + for (size_t i = 0; i < functions.size(); ++i) { + functions[i]->reset(); + } +} + +DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepthForFunction(FunctionNode* func) +{ + currentFunction = NULL; + resetFunctionNodes(); + + int maxCallDepth = func->detectCallDepth(this, 1); + + if (maxCallDepth == FunctionNode::kInfiniteCallDepth) + return kErrorRecursion; + + if (maxCallDepth >= maxDepth) + return kErrorMaxDepthExceeded; + + return kErrorNone; +} + +DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepth() +{ + if (maxDepth != FunctionNode::kInfiniteCallDepth) { + // Check all functions because the driver may fail on them + // TODO: Before detectingRecursion, strip unused functions. + for (size_t i = 0; i < functions.size(); ++i) { + ErrorCode error = detectCallDepthForFunction(functions[i]); + if (error != kErrorNone) + return error; + } + } else { + FunctionNode* main = findFunctionByName("main("); + if (main == NULL) + return kErrorMissingMain; + + return detectCallDepthForFunction(main); + } + + return kErrorNone; +} + +DetectCallDepth::FunctionNode* DetectCallDepth::findFunctionByName( + const TString& name) +{ + for (size_t i = 0; i < functions.size(); ++i) { + if (functions[i]->getName() == name) + return functions[i]; + } + return NULL; +} + diff --git a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h new file mode 100644 index 0000000000..5e7f23d15f --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h @@ -0,0 +1,80 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_DETECT_RECURSION_H_ +#define COMPILER_DETECT_RECURSION_H_ + +#include "GLSLANG/ShaderLang.h" + +#include +#include "compiler/translator/intermediate.h" +#include "compiler/translator/VariableInfo.h" + +class TInfoSink; + +// Traverses intermediate tree to detect function recursion. +class DetectCallDepth : public TIntermTraverser { +public: + enum ErrorCode { + kErrorMissingMain, + kErrorRecursion, + kErrorMaxDepthExceeded, + kErrorNone + }; + + DetectCallDepth(TInfoSink& infoSync, bool limitCallStackDepth, int maxCallStackDepth); + ~DetectCallDepth(); + + virtual bool visitAggregate(Visit, TIntermAggregate*); + + bool checkExceedsMaxDepth(int depth); + + ErrorCode detectCallDepth(); + +private: + class FunctionNode { + public: + static const int kInfiniteCallDepth = INT_MAX; + + FunctionNode(const TString& fname); + + const TString& getName() const; + + // If a function is already in the callee list, this becomes a no-op. + void addCallee(FunctionNode* callee); + + // Returns kInifinityCallDepth if recursive function calls are detected. + int detectCallDepth(DetectCallDepth* detectCallDepth, int depth); + + // Reset state. + void reset(); + + private: + // mangled function name is unique. + TString name; + + // functions that are directly called by this function. + TVector callees; + + Visit visit; + }; + + ErrorCode detectCallDepthForFunction(FunctionNode* func); + FunctionNode* findFunctionByName(const TString& name); + void resetFunctionNodes(); + + TInfoSink& getInfoSink() { return infoSink; } + + TVector functions; + FunctionNode* currentFunction; + TInfoSink& infoSink; + int maxDepth; + + DetectCallDepth(const DetectCallDepth&); + void operator=(const DetectCallDepth&); +}; + +#endif // COMPILER_DETECT_RECURSION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp new file mode 100644 index 0000000000..334eb0bfa8 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp @@ -0,0 +1,139 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Contains analysis utilities for dealing with HLSL's lack of support for +// the use of intrinsic functions which (implicitly or explicitly) compute +// gradients of functions with discontinuities. +// + +#include "compiler/translator/DetectDiscontinuity.h" + +#include "compiler/translator/ParseContext.h" + +namespace sh +{ +bool DetectLoopDiscontinuity::traverse(TIntermNode *node) +{ + mLoopDepth = 0; + mLoopDiscontinuity = false; + node->traverse(this); + return mLoopDiscontinuity; +} + +bool DetectLoopDiscontinuity::visitLoop(Visit visit, TIntermLoop *loop) +{ + if (visit == PreVisit) + { + ++mLoopDepth; + } + else if (visit == PostVisit) + { + --mLoopDepth; + } + + return true; +} + +bool DetectLoopDiscontinuity::visitBranch(Visit visit, TIntermBranch *node) +{ + if (mLoopDiscontinuity) + { + return false; + } + + if (!mLoopDepth) + { + return true; + } + + switch (node->getFlowOp()) + { + case EOpKill: + break; + case EOpBreak: + case EOpContinue: + case EOpReturn: + mLoopDiscontinuity = true; + break; + default: UNREACHABLE(); + } + + return !mLoopDiscontinuity; +} + +bool DetectLoopDiscontinuity::visitAggregate(Visit visit, TIntermAggregate *node) +{ + return !mLoopDiscontinuity; +} + +bool containsLoopDiscontinuity(TIntermNode *node) +{ + DetectLoopDiscontinuity detectLoopDiscontinuity; + return detectLoopDiscontinuity.traverse(node); +} + +bool DetectGradientOperation::traverse(TIntermNode *node) +{ + mGradientOperation = false; + node->traverse(this); + return mGradientOperation; +} + +bool DetectGradientOperation::visitUnary(Visit visit, TIntermUnary *node) +{ + if (mGradientOperation) + { + return false; + } + + switch (node->getOp()) + { + case EOpDFdx: + case EOpDFdy: + mGradientOperation = true; + default: + break; + } + + return !mGradientOperation; +} + +bool DetectGradientOperation::visitAggregate(Visit visit, TIntermAggregate *node) +{ + if (mGradientOperation) + { + return false; + } + + if (node->getOp() == EOpFunctionCall) + { + if (!node->isUserDefined()) + { + TString name = TFunction::unmangleName(node->getName()); + + if (name == "texture2D" || + name == "texture2DProj" || + name == "textureCube") + { + mGradientOperation = true; + } + } + else + { + // When a user defined function is called, we have to + // conservatively assume it to contain gradient operations + mGradientOperation = true; + } + } + + return !mGradientOperation; +} + +bool containsGradientOperation(TIntermNode *node) +{ + DetectGradientOperation detectGradientOperation; + return detectGradientOperation.traverse(node); +} +} diff --git a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h new file mode 100644 index 0000000000..1dd8be9233 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h @@ -0,0 +1,52 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Contains analysis utilities for dealing with HLSL's lack of support for +// the use of intrinsic functions which (implicitly or explicitly) compute +// gradients of functions with discontinuities. +// + +#ifndef COMPILER_DETECTDISCONTINUITY_H_ +#define COMPILER_DETECTDISCONTINUITY_H_ + +#include "compiler/translator/intermediate.h" + +namespace sh +{ +// Checks whether a loop can run for a variable number of iterations +class DetectLoopDiscontinuity : public TIntermTraverser +{ + public: + bool traverse(TIntermNode *node); + + protected: + bool visitBranch(Visit visit, TIntermBranch *node); + bool visitLoop(Visit visit, TIntermLoop *loop); + bool visitAggregate(Visit visit, TIntermAggregate *node); + + int mLoopDepth; + bool mLoopDiscontinuity; +}; + +bool containsLoopDiscontinuity(TIntermNode *node); + +// Checks for intrinsic functions which compute gradients +class DetectGradientOperation : public TIntermTraverser +{ + public: + bool traverse(TIntermNode *node); + + protected: + bool visitUnary(Visit visit, TIntermUnary *node); + bool visitAggregate(Visit visit, TIntermAggregate *node); + + bool mGradientOperation; +}; + +bool containsGradientOperation(TIntermNode *node); + +} + +#endif // COMPILER_DETECTDISCONTINUITY_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp b/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp new file mode 100644 index 0000000000..99506c0849 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp @@ -0,0 +1,63 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/Diagnostics.h" + +#include "compiler/translator/compilerdebug.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/preprocessor/SourceLocation.h" + +TDiagnostics::TDiagnostics(TInfoSink& infoSink) : + mInfoSink(infoSink), + mNumErrors(0), + mNumWarnings(0) +{ +} + +TDiagnostics::~TDiagnostics() +{ +} + +void TDiagnostics::writeInfo(Severity severity, + const pp::SourceLocation& loc, + const std::string& reason, + const std::string& token, + const std::string& extra) +{ + TPrefixType prefix = EPrefixNone; + switch (severity) + { + case PP_ERROR: + ++mNumErrors; + prefix = EPrefixError; + break; + case PP_WARNING: + ++mNumWarnings; + prefix = EPrefixWarning; + break; + default: + UNREACHABLE(); + break; + } + + TInfoSinkBase& sink = mInfoSink.info; + /* VC++ format: file(linenum) : error #: 'token' : extrainfo */ + sink.prefix(prefix); + sink.location(loc.file, loc.line); + sink << "'" << token << "' : " << reason << " " << extra << "\n"; +} + +void TDiagnostics::writeDebug(const std::string& str) +{ + mInfoSink.debug << str; +} + +void TDiagnostics::print(ID id, + const pp::SourceLocation& loc, + const std::string& text) +{ + writeInfo(severity(id), loc, message(id), text, ""); +} diff --git a/src/3rdparty/angle/src/compiler/translator/Diagnostics.h b/src/3rdparty/angle/src/compiler/translator/Diagnostics.h new file mode 100644 index 0000000000..cb71bb1204 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/Diagnostics.h @@ -0,0 +1,44 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_DIAGNOSTICS_H_ +#define COMPILER_DIAGNOSTICS_H_ + +#include "compiler/preprocessor/DiagnosticsBase.h" + +class TInfoSink; + +class TDiagnostics : public pp::Diagnostics +{ + public: + TDiagnostics(TInfoSink& infoSink); + virtual ~TDiagnostics(); + + TInfoSink& infoSink() { return mInfoSink; } + + int numErrors() const { return mNumErrors; } + int numWarnings() const { return mNumWarnings; } + + void writeInfo(Severity severity, + const pp::SourceLocation& loc, + const std::string& reason, + const std::string& token, + const std::string& extra); + + void writeDebug(const std::string& str); + + protected: + virtual void print(ID id, + const pp::SourceLocation& loc, + const std::string& text); + + private: + TInfoSink& mInfoSink; + int mNumErrors; + int mNumWarnings; +}; + +#endif // COMPILER_DIAGNOSTICS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp new file mode 100644 index 0000000000..662c8ae624 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp @@ -0,0 +1,161 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/DirectiveHandler.h" + +#include + +#include "compiler/translator/compilerdebug.h" +#include "compiler/translator/Diagnostics.h" + +static TBehavior getBehavior(const std::string& str) +{ + static const std::string kRequire("require"); + static const std::string kEnable("enable"); + static const std::string kDisable("disable"); + static const std::string kWarn("warn"); + + if (str == kRequire) return EBhRequire; + else if (str == kEnable) return EBhEnable; + else if (str == kDisable) return EBhDisable; + else if (str == kWarn) return EBhWarn; + return EBhUndefined; +} + +TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior, + TDiagnostics& diagnostics) + : mExtensionBehavior(extBehavior), + mDiagnostics(diagnostics) +{ +} + +TDirectiveHandler::~TDirectiveHandler() +{ +} + +void TDirectiveHandler::handleError(const pp::SourceLocation& loc, + const std::string& msg) +{ + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, msg, "", ""); +} + +void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc, + const std::string& name, + const std::string& value) +{ + static const std::string kSTDGL("STDGL"); + static const std::string kOptimize("optimize"); + static const std::string kDebug("debug"); + static const std::string kOn("on"); + static const std::string kOff("off"); + + bool invalidValue = false; + if (name == kSTDGL) + { + // The STDGL pragma is used to reserve pragmas for use by future + // revisions of GLSL. Ignore it. + return; + } + else if (name == kOptimize) + { + if (value == kOn) mPragma.optimize = true; + else if (value == kOff) mPragma.optimize = false; + else invalidValue = true; + } + else if (name == kDebug) + { + if (value == kOn) mPragma.debug = true; + else if (value == kOff) mPragma.debug = false; + else invalidValue = true; + } + else + { + mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name); + return; + } + + if (invalidValue) + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, + "invalid pragma value", value, + "'on' or 'off' expected"); +} + +void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc, + const std::string& name, + const std::string& behavior) +{ + static const std::string kExtAll("all"); + + TBehavior behaviorVal = getBehavior(behavior); + if (behaviorVal == EBhUndefined) + { + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, + "behavior", name, "invalid"); + return; + } + + if (name == kExtAll) + { + if (behaviorVal == EBhRequire) + { + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, + "extension", name, + "cannot have 'require' behavior"); + } + else if (behaviorVal == EBhEnable) + { + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, + "extension", name, + "cannot have 'enable' behavior"); + } + else + { + for (TExtensionBehavior::iterator iter = mExtensionBehavior.begin(); + iter != mExtensionBehavior.end(); ++iter) + iter->second = behaviorVal; + } + return; + } + + TExtensionBehavior::iterator iter = mExtensionBehavior.find(name); + if (iter != mExtensionBehavior.end()) + { + iter->second = behaviorVal; + return; + } + + pp::Diagnostics::Severity severity = pp::Diagnostics::PP_ERROR; + switch (behaviorVal) { + case EBhRequire: + severity = pp::Diagnostics::PP_ERROR; + break; + case EBhEnable: + case EBhWarn: + case EBhDisable: + severity = pp::Diagnostics::PP_WARNING; + break; + default: + UNREACHABLE(); + break; + } + mDiagnostics.writeInfo(severity, loc, + "extension", name, "is not supported"); +} + +void TDirectiveHandler::handleVersion(const pp::SourceLocation& loc, + int version) +{ + static const int kVersion = 100; + + if (version != kVersion) + { + std::stringstream stream; + stream << version; + std::string str = stream.str(); + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, + "version number", str, "not supported"); + } +} diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h new file mode 100644 index 0000000000..eb5f055494 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h @@ -0,0 +1,46 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_DIRECTIVE_HANDLER_H_ +#define COMPILER_DIRECTIVE_HANDLER_H_ + +#include "compiler/translator/ExtensionBehavior.h" +#include "compiler/translator/Pragma.h" +#include "compiler/preprocessor/DirectiveHandlerBase.h" + +class TDiagnostics; + +class TDirectiveHandler : public pp::DirectiveHandler +{ + public: + TDirectiveHandler(TExtensionBehavior& extBehavior, + TDiagnostics& diagnostics); + virtual ~TDirectiveHandler(); + + const TPragma& pragma() const { return mPragma; } + const TExtensionBehavior& extensionBehavior() const { return mExtensionBehavior; } + + virtual void handleError(const pp::SourceLocation& loc, + const std::string& msg); + + virtual void handlePragma(const pp::SourceLocation& loc, + const std::string& name, + const std::string& value); + + virtual void handleExtension(const pp::SourceLocation& loc, + const std::string& name, + const std::string& behavior); + + virtual void handleVersion(const pp::SourceLocation& loc, + int version); + + private: + TPragma mPragma; + TExtensionBehavior& mExtensionBehavior; + TDiagnostics& mDiagnostics; +}; + +#endif // COMPILER_DIRECTIVE_HANDLER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h new file mode 100644 index 0000000000..5c1595fb21 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h @@ -0,0 +1,37 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _EXTENSION_BEHAVIOR_INCLUDED_ +#define _EXTENSION_BEHAVIOR_INCLUDED_ + +#include +#include + +typedef enum +{ + EBhRequire, + EBhEnable, + EBhWarn, + EBhDisable, + EBhUndefined +} TBehavior; + +inline const char* getBehaviorString(TBehavior b) +{ + switch(b) + { + case EBhRequire: return "require"; + case EBhEnable: return "enable"; + case EBhWarn: return "warn"; + case EBhDisable: return "disable"; + default: return NULL; + } +} + +// Mapping between extension name and behavior. +typedef std::map TExtensionBehavior; + +#endif // _EXTENSION_TABLE_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.cpp b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.cpp new file mode 100644 index 0000000000..89e6f1a62b --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.cpp @@ -0,0 +1,215 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/ForLoopUnroll.h" + +namespace { + +class IntegerForLoopUnrollMarker : public TIntermTraverser { +public: + + virtual bool visitLoop(Visit, TIntermLoop* node) + { + // This is called after ValidateLimitations pass, so all the ASSERT + // should never fail. + // See ValidateLimitations::validateForLoopInit(). + ASSERT(node); + ASSERT(node->getType() == ELoopFor); + ASSERT(node->getInit()); + TIntermAggregate* decl = node->getInit()->getAsAggregate(); + ASSERT(decl && decl->getOp() == EOpDeclaration); + TIntermSequence& declSeq = decl->getSequence(); + ASSERT(declSeq.size() == 1); + TIntermBinary* declInit = declSeq[0]->getAsBinaryNode(); + ASSERT(declInit && declInit->getOp() == EOpInitialize); + ASSERT(declInit->getLeft()); + TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode(); + ASSERT(symbol); + TBasicType type = symbol->getBasicType(); + ASSERT(type == EbtInt || type == EbtFloat); + if (type == EbtInt) + node->setUnrollFlag(true); + return true; + } + +}; + +} // anonymous namepsace + +void ForLoopUnroll::FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info) +{ + ASSERT(node->getType() == ELoopFor); + ASSERT(node->getUnrollFlag()); + + TIntermNode* init = node->getInit(); + ASSERT(init != NULL); + TIntermAggregate* decl = init->getAsAggregate(); + ASSERT((decl != NULL) && (decl->getOp() == EOpDeclaration)); + TIntermSequence& declSeq = decl->getSequence(); + ASSERT(declSeq.size() == 1); + TIntermBinary* declInit = declSeq[0]->getAsBinaryNode(); + ASSERT((declInit != NULL) && (declInit->getOp() == EOpInitialize)); + TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode(); + ASSERT(symbol != NULL); + ASSERT(symbol->getBasicType() == EbtInt); + + info.id = symbol->getId(); + + ASSERT(declInit->getRight() != NULL); + TIntermConstantUnion* initNode = declInit->getRight()->getAsConstantUnion(); + ASSERT(initNode != NULL); + + info.initValue = evaluateIntConstant(initNode); + info.currentValue = info.initValue; + + TIntermNode* cond = node->getCondition(); + ASSERT(cond != NULL); + TIntermBinary* binOp = cond->getAsBinaryNode(); + ASSERT(binOp != NULL); + ASSERT(binOp->getRight() != NULL); + ASSERT(binOp->getRight()->getAsConstantUnion() != NULL); + + info.incrementValue = getLoopIncrement(node); + info.stopValue = evaluateIntConstant( + binOp->getRight()->getAsConstantUnion()); + info.op = binOp->getOp(); +} + +void ForLoopUnroll::Step() +{ + ASSERT(mLoopIndexStack.size() > 0); + TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1]; + info.currentValue += info.incrementValue; +} + +bool ForLoopUnroll::SatisfiesLoopCondition() +{ + ASSERT(mLoopIndexStack.size() > 0); + TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1]; + // Relational operator is one of: > >= < <= == or !=. + switch (info.op) { + case EOpEqual: + return (info.currentValue == info.stopValue); + case EOpNotEqual: + return (info.currentValue != info.stopValue); + case EOpLessThan: + return (info.currentValue < info.stopValue); + case EOpGreaterThan: + return (info.currentValue > info.stopValue); + case EOpLessThanEqual: + return (info.currentValue <= info.stopValue); + case EOpGreaterThanEqual: + return (info.currentValue >= info.stopValue); + default: + UNREACHABLE(); + } + return false; +} + +bool ForLoopUnroll::NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol) +{ + for (TVector::iterator i = mLoopIndexStack.begin(); + i != mLoopIndexStack.end(); + ++i) { + if (i->id == symbol->getId()) + return true; + } + return false; +} + +int ForLoopUnroll::GetLoopIndexValue(TIntermSymbol* symbol) +{ + for (TVector::iterator i = mLoopIndexStack.begin(); + i != mLoopIndexStack.end(); + ++i) { + if (i->id == symbol->getId()) + return i->currentValue; + } + UNREACHABLE(); + return false; +} + +void ForLoopUnroll::Push(TLoopIndexInfo& info) +{ + mLoopIndexStack.push_back(info); +} + +void ForLoopUnroll::Pop() +{ + mLoopIndexStack.pop_back(); +} + +// static +void ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling( + TIntermNode* root) +{ + ASSERT(root); + + IntegerForLoopUnrollMarker marker; + root->traverse(&marker); +} + +int ForLoopUnroll::getLoopIncrement(TIntermLoop* node) +{ + TIntermNode* expr = node->getExpression(); + ASSERT(expr != NULL); + // for expression has one of the following forms: + // loop_index++ + // loop_index-- + // loop_index += constant_expression + // loop_index -= constant_expression + // ++loop_index + // --loop_index + // The last two forms are not specified in the spec, but I am assuming + // its an oversight. + TIntermUnary* unOp = expr->getAsUnaryNode(); + TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode(); + + TOperator op = EOpNull; + TIntermConstantUnion* incrementNode = NULL; + if (unOp != NULL) { + op = unOp->getOp(); + } else if (binOp != NULL) { + op = binOp->getOp(); + ASSERT(binOp->getRight() != NULL); + incrementNode = binOp->getRight()->getAsConstantUnion(); + ASSERT(incrementNode != NULL); + } + + int increment = 0; + // The operator is one of: ++ -- += -=. + switch (op) { + case EOpPostIncrement: + case EOpPreIncrement: + ASSERT((unOp != NULL) && (binOp == NULL)); + increment = 1; + break; + case EOpPostDecrement: + case EOpPreDecrement: + ASSERT((unOp != NULL) && (binOp == NULL)); + increment = -1; + break; + case EOpAddAssign: + ASSERT((unOp == NULL) && (binOp != NULL)); + increment = evaluateIntConstant(incrementNode); + break; + case EOpSubAssign: + ASSERT((unOp == NULL) && (binOp != NULL)); + increment = - evaluateIntConstant(incrementNode); + break; + default: + ASSERT(false); + } + + return increment; +} + +int ForLoopUnroll::evaluateIntConstant(TIntermConstantUnion* node) +{ + ASSERT((node != NULL) && (node->getUnionArrayPointer() != NULL)); + return node->getIConst(0); +} + diff --git a/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h new file mode 100644 index 0000000000..afd70d1fd2 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h @@ -0,0 +1,52 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_FORLOOPUNROLL_H_ +#define COMPILER_FORLOOPUNROLL_H_ + +#include "compiler/translator/intermediate.h" + +struct TLoopIndexInfo { + int id; + int initValue; + int stopValue; + int incrementValue; + TOperator op; + int currentValue; +}; + +class ForLoopUnroll { +public: + ForLoopUnroll() { } + + void FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info); + + // Update the info.currentValue for the next loop iteration. + void Step(); + + // Return false if loop condition is no longer satisfied. + bool SatisfiesLoopCondition(); + + // Check if the symbol is the index of a loop that's unrolled. + bool NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol); + + // Return the current value of a given loop index symbol. + int GetLoopIndexValue(TIntermSymbol* symbol); + + void Push(TLoopIndexInfo& info); + void Pop(); + + static void MarkForLoopsWithIntegerIndicesForUnrolling(TIntermNode* root); + +private: + int getLoopIncrement(TIntermLoop* node); + + int evaluateIntConstant(TIntermConstantUnion* node); + + TVector mLoopIndexStack; +}; + +#endif diff --git a/src/3rdparty/angle/src/compiler/translator/HashNames.h b/src/3rdparty/angle/src/compiler/translator/HashNames.h new file mode 100644 index 0000000000..751265b759 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/HashNames.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_HASH_NAMES_H_ +#define COMPILER_HASH_NAMES_H_ + +#include + +#include "compiler/translator/intermediate.h" +#include "GLSLANG/ShaderLang.h" + +#define HASHED_NAME_PREFIX "webgl_" + +typedef std::map NameMap; + +#endif // COMPILER_HASH_NAMES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp b/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp new file mode 100644 index 0000000000..cd59658ff7 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp @@ -0,0 +1,54 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/InfoSink.h" + +void TInfoSinkBase::prefix(TPrefixType p) { + switch(p) { + case EPrefixNone: + break; + case EPrefixWarning: + sink.append("WARNING: "); + break; + case EPrefixError: + sink.append("ERROR: "); + break; + case EPrefixInternalError: + sink.append("INTERNAL ERROR: "); + break; + case EPrefixUnimplemented: + sink.append("UNIMPLEMENTED: "); + break; + case EPrefixNote: + sink.append("NOTE: "); + break; + default: + sink.append("UNKOWN ERROR: "); + break; + } +} + +void TInfoSinkBase::location(int file, int line) { + TPersistStringStream stream; + if (line) + stream << file << ":" << line; + else + stream << file << ":? "; + stream << ": "; + + sink.append(stream.str()); +} + +void TInfoSinkBase::location(const TSourceLoc& loc) { + location(loc.first_file, loc.first_line); +} + +void TInfoSinkBase::message(TPrefixType p, const TSourceLoc& loc, const char* m) { + prefix(p); + location(loc); + sink.append(m); + sink.append("\n"); +} diff --git a/src/3rdparty/angle/src/compiler/translator/InfoSink.h b/src/3rdparty/angle/src/compiler/translator/InfoSink.h new file mode 100644 index 0000000000..698a8b454b --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/InfoSink.h @@ -0,0 +1,116 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _INFOSINK_INCLUDED_ +#define _INFOSINK_INCLUDED_ + +#include +#include +#include "compiler/translator/Common.h" + +// Returns the fractional part of the given floating-point number. +inline float fractionalPart(float f) { + float intPart = 0.0f; + return modff(f, &intPart); +} + +// +// TPrefixType is used to centralize how info log messages start. +// See below. +// +enum TPrefixType { + EPrefixNone, + EPrefixWarning, + EPrefixError, + EPrefixInternalError, + EPrefixUnimplemented, + EPrefixNote +}; + +// +// Encapsulate info logs for all objects that have them. +// +// The methods are a general set of tools for getting a variety of +// messages and types inserted into the log. +// +class TInfoSinkBase { +public: + TInfoSinkBase() {} + + template + TInfoSinkBase& operator<<(const T& t) { + TPersistStringStream stream; + stream << t; + sink.append(stream.str()); + return *this; + } + // Override << operator for specific types. It is faster to append strings + // and characters directly to the sink. + TInfoSinkBase& operator<<(char c) { + sink.append(1, c); + return *this; + } + TInfoSinkBase& operator<<(const char* str) { + sink.append(str); + return *this; + } + TInfoSinkBase& operator<<(const TPersistString& str) { + sink.append(str); + return *this; + } + TInfoSinkBase& operator<<(const TString& str) { + sink.append(str.c_str()); + return *this; + } + // Make sure floats are written with correct precision. + TInfoSinkBase& operator<<(float f) { + // Make sure that at least one decimal point is written. If a number + // does not have a fractional part, the default precision format does + // not write the decimal portion which gets interpreted as integer by + // the compiler. + TPersistStringStream stream; + if (fractionalPart(f) == 0.0f) { + stream.precision(1); + stream << std::showpoint << std::fixed << f; + } else { + stream.unsetf(std::ios::fixed); + stream.unsetf(std::ios::scientific); + stream.precision(8); + stream << f; + } + sink.append(stream.str()); + return *this; + } + // Write boolean values as their names instead of integral value. + TInfoSinkBase& operator<<(bool b) { + const char* str = b ? "true" : "false"; + sink.append(str); + return *this; + } + + void erase() { sink.clear(); } + int size() { return static_cast(sink.size()); } + + const TPersistString& str() const { return sink; } + const char* c_str() const { return sink.c_str(); } + + void prefix(TPrefixType p); + void location(int file, int line); + void location(const TSourceLoc& loc); + void message(TPrefixType p, const TSourceLoc& loc, const char* m); + +private: + TPersistString sink; +}; + +class TInfoSink { +public: + TInfoSinkBase info; + TInfoSinkBase debug; + TInfoSinkBase obj; +}; + +#endif // _INFOSINK_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp new file mode 100644 index 0000000000..db728b2129 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp @@ -0,0 +1,564 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// +// Create strings that declare built-in definitions, add built-ins that +// cannot be expressed in the files, and establish mappings between +// built-in functions and operators. +// + +#include "compiler/translator/Initialize.h" + +#include "compiler/translator/intermediate.h" + +void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable) +{ + TType *float1 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 1); + TType *float2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2); + TType *float3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3); + TType *float4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4); + + TType *int2 = new TType(EbtInt, EbpUndefined, EvqGlobal, 2); + TType *int3 = new TType(EbtInt, EbpUndefined, EvqGlobal, 3); + TType *int4 = new TType(EbtInt, EbpUndefined, EvqGlobal, 4); + + // + // Angle and Trigonometric Functions. + // + symbolTable.insertBuiltIn(float1, "radians", float1); + symbolTable.insertBuiltIn(float2, "radians", float2); + symbolTable.insertBuiltIn(float3, "radians", float3); + symbolTable.insertBuiltIn(float4, "radians", float4); + + symbolTable.insertBuiltIn(float1, "degrees", float1); + symbolTable.insertBuiltIn(float2, "degrees", float2); + symbolTable.insertBuiltIn(float3, "degrees", float3); + symbolTable.insertBuiltIn(float4, "degrees", float4); + + symbolTable.insertBuiltIn(float1, "sin", float1); + symbolTable.insertBuiltIn(float2, "sin", float2); + symbolTable.insertBuiltIn(float3, "sin", float3); + symbolTable.insertBuiltIn(float4, "sin", float4); + + symbolTable.insertBuiltIn(float1, "cos", float1); + symbolTable.insertBuiltIn(float2, "cos", float2); + symbolTable.insertBuiltIn(float3, "cos", float3); + symbolTable.insertBuiltIn(float4, "cos", float4); + + symbolTable.insertBuiltIn(float1, "tan", float1); + symbolTable.insertBuiltIn(float2, "tan", float2); + symbolTable.insertBuiltIn(float3, "tan", float3); + symbolTable.insertBuiltIn(float4, "tan", float4); + + symbolTable.insertBuiltIn(float1, "asin", float1); + symbolTable.insertBuiltIn(float2, "asin", float2); + symbolTable.insertBuiltIn(float3, "asin", float3); + symbolTable.insertBuiltIn(float4, "asin", float4); + + symbolTable.insertBuiltIn(float1, "acos", float1); + symbolTable.insertBuiltIn(float2, "acos", float2); + symbolTable.insertBuiltIn(float3, "acos", float3); + symbolTable.insertBuiltIn(float4, "acos", float4); + + symbolTable.insertBuiltIn(float1, "atan", float1, float1); + symbolTable.insertBuiltIn(float2, "atan", float2, float2); + symbolTable.insertBuiltIn(float3, "atan", float3, float3); + symbolTable.insertBuiltIn(float4, "atan", float4, float4); + + symbolTable.insertBuiltIn(float1, "atan", float1); + symbolTable.insertBuiltIn(float2, "atan", float2); + symbolTable.insertBuiltIn(float3, "atan", float3); + symbolTable.insertBuiltIn(float4, "atan", float4); + + // + // Exponential Functions. + // + symbolTable.insertBuiltIn(float1, "pow", float1, float1); + symbolTable.insertBuiltIn(float2, "pow", float2, float2); + symbolTable.insertBuiltIn(float3, "pow", float3, float3); + symbolTable.insertBuiltIn(float4, "pow", float4, float4); + + symbolTable.insertBuiltIn(float1, "exp", float1); + symbolTable.insertBuiltIn(float2, "exp", float2); + symbolTable.insertBuiltIn(float3, "exp", float3); + symbolTable.insertBuiltIn(float4, "exp", float4); + + symbolTable.insertBuiltIn(float1, "log", float1); + symbolTable.insertBuiltIn(float2, "log", float2); + symbolTable.insertBuiltIn(float3, "log", float3); + symbolTable.insertBuiltIn(float4, "log", float4); + + symbolTable.insertBuiltIn(float1, "exp2", float1); + symbolTable.insertBuiltIn(float2, "exp2", float2); + symbolTable.insertBuiltIn(float3, "exp2", float3); + symbolTable.insertBuiltIn(float4, "exp2", float4); + + symbolTable.insertBuiltIn(float1, "log2", float1); + symbolTable.insertBuiltIn(float2, "log2", float2); + symbolTable.insertBuiltIn(float3, "log2", float3); + symbolTable.insertBuiltIn(float4, "log2", float4); + + symbolTable.insertBuiltIn(float1, "sqrt", float1); + symbolTable.insertBuiltIn(float2, "sqrt", float2); + symbolTable.insertBuiltIn(float3, "sqrt", float3); + symbolTable.insertBuiltIn(float4, "sqrt", float4); + + symbolTable.insertBuiltIn(float1, "inversesqrt", float1); + symbolTable.insertBuiltIn(float2, "inversesqrt", float2); + symbolTable.insertBuiltIn(float3, "inversesqrt", float3); + symbolTable.insertBuiltIn(float4, "inversesqrt", float4); + + // + // Common Functions. + // + symbolTable.insertBuiltIn(float1, "abs", float1); + symbolTable.insertBuiltIn(float2, "abs", float2); + symbolTable.insertBuiltIn(float3, "abs", float3); + symbolTable.insertBuiltIn(float4, "abs", float4); + + symbolTable.insertBuiltIn(float1, "sign", float1); + symbolTable.insertBuiltIn(float2, "sign", float2); + symbolTable.insertBuiltIn(float3, "sign", float3); + symbolTable.insertBuiltIn(float4, "sign", float4); + + symbolTable.insertBuiltIn(float1, "floor", float1); + symbolTable.insertBuiltIn(float2, "floor", float2); + symbolTable.insertBuiltIn(float3, "floor", float3); + symbolTable.insertBuiltIn(float4, "floor", float4); + + symbolTable.insertBuiltIn(float1, "ceil", float1); + symbolTable.insertBuiltIn(float2, "ceil", float2); + symbolTable.insertBuiltIn(float3, "ceil", float3); + symbolTable.insertBuiltIn(float4, "ceil", float4); + + symbolTable.insertBuiltIn(float1, "fract", float1); + symbolTable.insertBuiltIn(float2, "fract", float2); + symbolTable.insertBuiltIn(float3, "fract", float3); + symbolTable.insertBuiltIn(float4, "fract", float4); + + symbolTable.insertBuiltIn(float1, "mod", float1, float1); + symbolTable.insertBuiltIn(float2, "mod", float2, float1); + symbolTable.insertBuiltIn(float3, "mod", float3, float1); + symbolTable.insertBuiltIn(float4, "mod", float4, float1); + symbolTable.insertBuiltIn(float2, "mod", float2, float2); + symbolTable.insertBuiltIn(float3, "mod", float3, float3); + symbolTable.insertBuiltIn(float4, "mod", float4, float4); + + symbolTable.insertBuiltIn(float1, "min", float1, float1); + symbolTable.insertBuiltIn(float2, "min", float2, float1); + symbolTable.insertBuiltIn(float3, "min", float3, float1); + symbolTable.insertBuiltIn(float4, "min", float4, float1); + symbolTable.insertBuiltIn(float2, "min", float2, float2); + symbolTable.insertBuiltIn(float3, "min", float3, float3); + symbolTable.insertBuiltIn(float4, "min", float4, float4); + + symbolTable.insertBuiltIn(float1, "max", float1, float1); + symbolTable.insertBuiltIn(float2, "max", float2, float1); + symbolTable.insertBuiltIn(float3, "max", float3, float1); + symbolTable.insertBuiltIn(float4, "max", float4, float1); + symbolTable.insertBuiltIn(float2, "max", float2, float2); + symbolTable.insertBuiltIn(float3, "max", float3, float3); + symbolTable.insertBuiltIn(float4, "max", float4, float4); + + symbolTable.insertBuiltIn(float1, "clamp", float1, float1, float1); + symbolTable.insertBuiltIn(float2, "clamp", float2, float1, float1); + symbolTable.insertBuiltIn(float3, "clamp", float3, float1, float1); + symbolTable.insertBuiltIn(float4, "clamp", float4, float1, float1); + symbolTable.insertBuiltIn(float2, "clamp", float2, float2, float2); + symbolTable.insertBuiltIn(float3, "clamp", float3, float3, float3); + symbolTable.insertBuiltIn(float4, "clamp", float4, float4, float4); + + symbolTable.insertBuiltIn(float1, "mix", float1, float1, float1); + symbolTable.insertBuiltIn(float2, "mix", float2, float2, float1); + symbolTable.insertBuiltIn(float3, "mix", float3, float3, float1); + symbolTable.insertBuiltIn(float4, "mix", float4, float4, float1); + symbolTable.insertBuiltIn(float2, "mix", float2, float2, float2); + symbolTable.insertBuiltIn(float3, "mix", float3, float3, float3); + symbolTable.insertBuiltIn(float4, "mix", float4, float4, float4); + + symbolTable.insertBuiltIn(float1, "step", float1, float1); + symbolTable.insertBuiltIn(float2, "step", float2, float2); + symbolTable.insertBuiltIn(float3, "step", float3, float3); + symbolTable.insertBuiltIn(float4, "step", float4, float4); + symbolTable.insertBuiltIn(float2, "step", float1, float2); + symbolTable.insertBuiltIn(float3, "step", float1, float3); + symbolTable.insertBuiltIn(float4, "step", float1, float4); + + symbolTable.insertBuiltIn(float1, "smoothstep", float1, float1, float1); + symbolTable.insertBuiltIn(float2, "smoothstep", float2, float2, float2); + symbolTable.insertBuiltIn(float3, "smoothstep", float3, float3, float3); + symbolTable.insertBuiltIn(float4, "smoothstep", float4, float4, float4); + symbolTable.insertBuiltIn(float2, "smoothstep", float1, float1, float2); + symbolTable.insertBuiltIn(float3, "smoothstep", float1, float1, float3); + symbolTable.insertBuiltIn(float4, "smoothstep", float1, float1, float4); + + // + // Geometric Functions. + // + symbolTable.insertBuiltIn(float1, "length", float1); + symbolTable.insertBuiltIn(float1, "length", float2); + symbolTable.insertBuiltIn(float1, "length", float3); + symbolTable.insertBuiltIn(float1, "length", float4); + + symbolTable.insertBuiltIn(float1, "distance", float1, float1); + symbolTable.insertBuiltIn(float1, "distance", float2, float2); + symbolTable.insertBuiltIn(float1, "distance", float3, float3); + symbolTable.insertBuiltIn(float1, "distance", float4, float4); + + symbolTable.insertBuiltIn(float1, "dot", float1, float1); + symbolTable.insertBuiltIn(float1, "dot", float2, float2); + symbolTable.insertBuiltIn(float1, "dot", float3, float3); + symbolTable.insertBuiltIn(float1, "dot", float4, float4); + + symbolTable.insertBuiltIn(float3, "cross", float3, float3); + symbolTable.insertBuiltIn(float1, "normalize", float1); + symbolTable.insertBuiltIn(float2, "normalize", float2); + symbolTable.insertBuiltIn(float3, "normalize", float3); + symbolTable.insertBuiltIn(float4, "normalize", float4); + + symbolTable.insertBuiltIn(float1, "faceforward", float1, float1, float1); + symbolTable.insertBuiltIn(float2, "faceforward", float2, float2, float2); + symbolTable.insertBuiltIn(float3, "faceforward", float3, float3, float3); + symbolTable.insertBuiltIn(float4, "faceforward", float4, float4, float4); + + symbolTable.insertBuiltIn(float1, "reflect", float1, float1); + symbolTable.insertBuiltIn(float2, "reflect", float2, float2); + symbolTable.insertBuiltIn(float3, "reflect", float3, float3); + symbolTable.insertBuiltIn(float4, "reflect", float4, float4); + + symbolTable.insertBuiltIn(float1, "refract", float1, float1, float1); + symbolTable.insertBuiltIn(float2, "refract", float2, float2, float1); + symbolTable.insertBuiltIn(float3, "refract", float3, float3, float1); + symbolTable.insertBuiltIn(float4, "refract", float4, float4, float1); + + TType *mat2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2, true); + TType *mat3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3, true); + TType *mat4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4, true); + + // + // Matrix Functions. + // + symbolTable.insertBuiltIn(mat2, "matrixCompMult", mat2, mat2); + symbolTable.insertBuiltIn(mat3, "matrixCompMult", mat3, mat3); + symbolTable.insertBuiltIn(mat4, "matrixCompMult", mat4, mat4); + + TType *bool1 = new TType(EbtBool, EbpUndefined, EvqGlobal, 1); + TType *bool2 = new TType(EbtBool, EbpUndefined, EvqGlobal, 2); + TType *bool3 = new TType(EbtBool, EbpUndefined, EvqGlobal, 3); + TType *bool4 = new TType(EbtBool, EbpUndefined, EvqGlobal, 4); + + // + // Vector relational functions. + // + symbolTable.insertBuiltIn(bool2, "lessThan", float2, float2); + symbolTable.insertBuiltIn(bool3, "lessThan", float3, float3); + symbolTable.insertBuiltIn(bool4, "lessThan", float4, float4); + + symbolTable.insertBuiltIn(bool2, "lessThan", int2, int2); + symbolTable.insertBuiltIn(bool3, "lessThan", int3, int3); + symbolTable.insertBuiltIn(bool4, "lessThan", int4, int4); + + symbolTable.insertBuiltIn(bool2, "lessThanEqual", float2, float2); + symbolTable.insertBuiltIn(bool3, "lessThanEqual", float3, float3); + symbolTable.insertBuiltIn(bool4, "lessThanEqual", float4, float4); + + symbolTable.insertBuiltIn(bool2, "lessThanEqual", int2, int2); + symbolTable.insertBuiltIn(bool3, "lessThanEqual", int3, int3); + symbolTable.insertBuiltIn(bool4, "lessThanEqual", int4, int4); + + symbolTable.insertBuiltIn(bool2, "greaterThan", float2, float2); + symbolTable.insertBuiltIn(bool3, "greaterThan", float3, float3); + symbolTable.insertBuiltIn(bool4, "greaterThan", float4, float4); + + symbolTable.insertBuiltIn(bool2, "greaterThan", int2, int2); + symbolTable.insertBuiltIn(bool3, "greaterThan", int3, int3); + symbolTable.insertBuiltIn(bool4, "greaterThan", int4, int4); + + symbolTable.insertBuiltIn(bool2, "greaterThanEqual", float2, float2); + symbolTable.insertBuiltIn(bool3, "greaterThanEqual", float3, float3); + symbolTable.insertBuiltIn(bool4, "greaterThanEqual", float4, float4); + + symbolTable.insertBuiltIn(bool2, "greaterThanEqual", int2, int2); + symbolTable.insertBuiltIn(bool3, "greaterThanEqual", int3, int3); + symbolTable.insertBuiltIn(bool4, "greaterThanEqual", int4, int4); + + symbolTable.insertBuiltIn(bool2, "equal", float2, float2); + symbolTable.insertBuiltIn(bool3, "equal", float3, float3); + symbolTable.insertBuiltIn(bool4, "equal", float4, float4); + + symbolTable.insertBuiltIn(bool2, "equal", int2, int2); + symbolTable.insertBuiltIn(bool3, "equal", int3, int3); + symbolTable.insertBuiltIn(bool4, "equal", int4, int4); + + symbolTable.insertBuiltIn(bool2, "equal", bool2, bool2); + symbolTable.insertBuiltIn(bool3, "equal", bool3, bool3); + symbolTable.insertBuiltIn(bool4, "equal", bool4, bool4); + + symbolTable.insertBuiltIn(bool2, "notEqual", float2, float2); + symbolTable.insertBuiltIn(bool3, "notEqual", float3, float3); + symbolTable.insertBuiltIn(bool4, "notEqual", float4, float4); + + symbolTable.insertBuiltIn(bool2, "notEqual", int2, int2); + symbolTable.insertBuiltIn(bool3, "notEqual", int3, int3); + symbolTable.insertBuiltIn(bool4, "notEqual", int4, int4); + + symbolTable.insertBuiltIn(bool2, "notEqual", bool2, bool2); + symbolTable.insertBuiltIn(bool3, "notEqual", bool3, bool3); + symbolTable.insertBuiltIn(bool4, "notEqual", bool4, bool4); + + symbolTable.insertBuiltIn(bool1, "any", bool2); + symbolTable.insertBuiltIn(bool1, "any", bool3); + symbolTable.insertBuiltIn(bool1, "any", bool4); + + symbolTable.insertBuiltIn(bool1, "all", bool2); + symbolTable.insertBuiltIn(bool1, "all", bool3); + symbolTable.insertBuiltIn(bool1, "all", bool4); + + symbolTable.insertBuiltIn(bool2, "not", bool2); + symbolTable.insertBuiltIn(bool3, "not", bool3); + symbolTable.insertBuiltIn(bool4, "not", bool4); + + TType *sampler2D = new TType(EbtSampler2D, EbpUndefined, EvqGlobal, 1); + TType *samplerCube = new TType(EbtSamplerCube, EbpUndefined, EvqGlobal, 1); + + // + // Texture Functions for GLSL ES 1.0 + // + symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2); + symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3); + symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4); + symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3); + + if (resources.OES_EGL_image_external) + { + TType *samplerExternalOES = new TType(EbtSamplerExternalOES, EbpUndefined, EvqGlobal, 1); + + symbolTable.insertBuiltIn(float4, "texture2D", samplerExternalOES, float2); + symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float3); + symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float4); + } + + if (resources.ARB_texture_rectangle) + { + TType *sampler2DRect = new TType(EbtSampler2DRect, EbpUndefined, EvqGlobal, 1); + + symbolTable.insertBuiltIn(float4, "texture2DRect", sampler2DRect, float2); + symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float3); + symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float4); + } + + if (type == SH_FRAGMENT_SHADER) + { + symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2, float1); + symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3, float1); + symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4, float1); + symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3, float1); + + if (resources.OES_standard_derivatives) + { + symbolTable.insertBuiltIn(float1, "dFdx", float1); + symbolTable.insertBuiltIn(float2, "dFdx", float2); + symbolTable.insertBuiltIn(float3, "dFdx", float3); + symbolTable.insertBuiltIn(float4, "dFdx", float4); + + symbolTable.insertBuiltIn(float1, "dFdy", float1); + symbolTable.insertBuiltIn(float2, "dFdy", float2); + symbolTable.insertBuiltIn(float3, "dFdy", float3); + symbolTable.insertBuiltIn(float4, "dFdy", float4); + + symbolTable.insertBuiltIn(float1, "fwidth", float1); + symbolTable.insertBuiltIn(float2, "fwidth", float2); + symbolTable.insertBuiltIn(float3, "fwidth", float3); + symbolTable.insertBuiltIn(float4, "fwidth", float4); + } + } + + if(type == SH_VERTEX_SHADER) + { + symbolTable.insertBuiltIn(float4, "texture2DLod", sampler2D, float2, float1); + symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float3, float1); + symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float4, float1); + symbolTable.insertBuiltIn(float4, "textureCubeLod", samplerCube, float3, float1); + } + + // + // Depth range in window coordinates + // + TFieldList *fields = NewPoolTFieldList(); + TField *near = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("near")); + TField *far = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("far")); + TField *diff = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("diff")); + fields->push_back(near); + fields->push_back(far); + fields->push_back(diff); + TStructure *depthRangeStruct = new TStructure(NewPoolTString("gl_DepthRangeParameters"), fields); + TVariable *depthRangeParameters = new TVariable(&depthRangeStruct->name(), depthRangeStruct, true); + symbolTable.insert(*depthRangeParameters); + TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(depthRangeStruct)); + depthRange->setQualifier(EvqUniform); + symbolTable.insert(*depthRange); + + // + // Implementation dependent built-in constants. + // + symbolTable.insertConstInt("gl_MaxVertexAttribs", resources.MaxVertexAttribs); + symbolTable.insertConstInt("gl_MaxVertexUniformVectors", resources.MaxVertexUniformVectors); + symbolTable.insertConstInt("gl_MaxVaryingVectors", resources.MaxVaryingVectors); + symbolTable.insertConstInt("gl_MaxVertexTextureImageUnits", resources.MaxVertexTextureImageUnits); + symbolTable.insertConstInt("gl_MaxCombinedTextureImageUnits", resources.MaxCombinedTextureImageUnits); + symbolTable.insertConstInt("gl_MaxTextureImageUnits", resources.MaxTextureImageUnits); + symbolTable.insertConstInt("gl_MaxFragmentUniformVectors", resources.MaxFragmentUniformVectors); + + if (spec != SH_CSS_SHADERS_SPEC) + { + symbolTable.insertConstInt("gl_MaxDrawBuffers", resources.MaxDrawBuffers); + } +} + +void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, + const ShBuiltInResources &resources, + TSymbolTable &symbolTable) +{ + // + // First, insert some special built-in variables that are not in + // the built-in header files. + // + switch(type) { + case SH_FRAGMENT_SHADER: + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4))); + symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1))); + symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2))); + + // + // In CSS Shaders, gl_FragColor, gl_FragData, and gl_MaxDrawBuffers are not available. + // Instead, css_MixColor and css_ColorMatrix are available. + // + if (spec != SH_CSS_SHADERS_SPEC) { + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4))); + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4))); + if (resources.EXT_frag_depth) { + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1))); + symbolTable.relateToExtension("gl_FragDepthEXT", "GL_EXT_frag_depth"); + } + } else { + symbolTable.insert(*new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4))); + symbolTable.insert(*new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, true))); + } + + break; + + case SH_VERTEX_SHADER: + symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4))); + symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EbpMedium, EvqPointSize, 1))); + break; + + default: assert(false && "Language not supported"); + } + + // + // Next, identify which built-ins from the already loaded headers have + // a mapping to an operator. Those that are not identified as such are + // expected to be resolved through a library of functions, versus as + // operations. + // + symbolTable.relateToOperator("matrixCompMult", EOpMul); + + symbolTable.relateToOperator("equal", EOpVectorEqual); + symbolTable.relateToOperator("notEqual", EOpVectorNotEqual); + symbolTable.relateToOperator("lessThan", EOpLessThan); + symbolTable.relateToOperator("greaterThan", EOpGreaterThan); + symbolTable.relateToOperator("lessThanEqual", EOpLessThanEqual); + symbolTable.relateToOperator("greaterThanEqual", EOpGreaterThanEqual); + + symbolTable.relateToOperator("radians", EOpRadians); + symbolTable.relateToOperator("degrees", EOpDegrees); + symbolTable.relateToOperator("sin", EOpSin); + symbolTable.relateToOperator("cos", EOpCos); + symbolTable.relateToOperator("tan", EOpTan); + symbolTable.relateToOperator("asin", EOpAsin); + symbolTable.relateToOperator("acos", EOpAcos); + symbolTable.relateToOperator("atan", EOpAtan); + + symbolTable.relateToOperator("pow", EOpPow); + symbolTable.relateToOperator("exp2", EOpExp2); + symbolTable.relateToOperator("log", EOpLog); + symbolTable.relateToOperator("exp", EOpExp); + symbolTable.relateToOperator("log2", EOpLog2); + symbolTable.relateToOperator("sqrt", EOpSqrt); + symbolTable.relateToOperator("inversesqrt", EOpInverseSqrt); + + symbolTable.relateToOperator("abs", EOpAbs); + symbolTable.relateToOperator("sign", EOpSign); + symbolTable.relateToOperator("floor", EOpFloor); + symbolTable.relateToOperator("ceil", EOpCeil); + symbolTable.relateToOperator("fract", EOpFract); + symbolTable.relateToOperator("mod", EOpMod); + symbolTable.relateToOperator("min", EOpMin); + symbolTable.relateToOperator("max", EOpMax); + symbolTable.relateToOperator("clamp", EOpClamp); + symbolTable.relateToOperator("mix", EOpMix); + symbolTable.relateToOperator("step", EOpStep); + symbolTable.relateToOperator("smoothstep", EOpSmoothStep); + + symbolTable.relateToOperator("length", EOpLength); + symbolTable.relateToOperator("distance", EOpDistance); + symbolTable.relateToOperator("dot", EOpDot); + symbolTable.relateToOperator("cross", EOpCross); + symbolTable.relateToOperator("normalize", EOpNormalize); + symbolTable.relateToOperator("faceforward", EOpFaceForward); + symbolTable.relateToOperator("reflect", EOpReflect); + symbolTable.relateToOperator("refract", EOpRefract); + + symbolTable.relateToOperator("any", EOpAny); + symbolTable.relateToOperator("all", EOpAll); + symbolTable.relateToOperator("not", EOpVectorLogicalNot); + + // Map language-specific operators. + switch(type) { + case SH_VERTEX_SHADER: + break; + case SH_FRAGMENT_SHADER: + if (resources.OES_standard_derivatives) { + symbolTable.relateToOperator("dFdx", EOpDFdx); + symbolTable.relateToOperator("dFdy", EOpDFdy); + symbolTable.relateToOperator("fwidth", EOpFwidth); + + symbolTable.relateToExtension("dFdx", "GL_OES_standard_derivatives"); + symbolTable.relateToExtension("dFdy", "GL_OES_standard_derivatives"); + symbolTable.relateToExtension("fwidth", "GL_OES_standard_derivatives"); + } + break; + default: break; + } + + // Finally add resource-specific variables. + switch(type) { + case SH_FRAGMENT_SHADER: + if (spec != SH_CSS_SHADERS_SPEC) { + // Set up gl_FragData. The array size. + TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, false, true); + fragData.setArraySize(resources.MaxDrawBuffers); + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData)); + } + break; + default: break; + } +} + +void InitExtensionBehavior(const ShBuiltInResources& resources, + TExtensionBehavior& extBehavior) +{ + if (resources.OES_standard_derivatives) + extBehavior["GL_OES_standard_derivatives"] = EBhUndefined; + if (resources.OES_EGL_image_external) + extBehavior["GL_OES_EGL_image_external"] = EBhUndefined; + if (resources.ARB_texture_rectangle) + extBehavior["GL_ARB_texture_rectangle"] = EBhUndefined; + if (resources.EXT_draw_buffers) + extBehavior["GL_EXT_draw_buffers"] = EBhUndefined; + if (resources.EXT_frag_depth) + extBehavior["GL_EXT_frag_depth"] = EBhUndefined; +} diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.h b/src/3rdparty/angle/src/compiler/translator/Initialize.h new file mode 100644 index 0000000000..b5642869aa --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/Initialize.h @@ -0,0 +1,23 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _INITIALIZE_INCLUDED_ +#define _INITIALIZE_INCLUDED_ + +#include "compiler/translator/Common.h" +#include "compiler/translator/ShHandle.h" +#include "compiler/translator/SymbolTable.h" + +void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table); + +void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, + const ShBuiltInResources& resources, + TSymbolTable& symbolTable); + +void InitExtensionBehavior(const ShBuiltInResources& resources, + TExtensionBehavior& extensionBehavior); + +#endif // _INITIALIZE_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp new file mode 100644 index 0000000000..43f81784d0 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp @@ -0,0 +1,32 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/InitializeDll.h" + +#include "compiler/translator/InitializeGlobals.h" +#include "compiler/translator/InitializeParseContext.h" +#include "compiler/translator/osinclude.h" + +bool InitProcess() +{ + if (!InitializePoolIndex()) { + assert(0 && "InitProcess(): Failed to initalize global pool"); + return false; + } + + if (!InitializeParseContextIndex()) { + assert(0 && "InitProcess(): Failed to initalize parse context"); + return false; + } + + return true; +} + +void DetachProcess() +{ + FreeParseContextIndex(); + FreePoolIndex(); +} diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeDll.h b/src/3rdparty/angle/src/compiler/translator/InitializeDll.h new file mode 100644 index 0000000000..43070cc3ff --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/InitializeDll.h @@ -0,0 +1,13 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +#ifndef __INITIALIZEDLL_H +#define __INITIALIZEDLL_H + +bool InitProcess(); +void DetachProcess(); + +#endif // __INITIALIZEDLL_H + diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h b/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h new file mode 100644 index 0000000000..0715941424 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h @@ -0,0 +1,13 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef __INITIALIZE_GLOBALS_INCLUDED_ +#define __INITIALIZE_GLOBALS_INCLUDED_ + +bool InitializePoolIndex(); +void FreePoolIndex(); + +#endif // __INITIALIZE_GLOBALS_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.cpp new file mode 100644 index 0000000000..b4defae569 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.cpp @@ -0,0 +1,40 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/InitializeParseContext.h" + +#include "compiler/translator/osinclude.h" + +OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX; + +bool InitializeParseContextIndex() +{ + assert(GlobalParseContextIndex == OS_INVALID_TLS_INDEX); + + GlobalParseContextIndex = OS_AllocTLSIndex(); + return GlobalParseContextIndex != OS_INVALID_TLS_INDEX; +} + +void FreeParseContextIndex() +{ + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + + OS_FreeTLSIndex(GlobalParseContextIndex); + GlobalParseContextIndex = OS_INVALID_TLS_INDEX; +} + +void SetGlobalParseContext(TParseContext* context) +{ + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + OS_SetTLSValue(GlobalParseContextIndex, context); +} + +TParseContext* GetGlobalParseContext() +{ + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + return static_cast(OS_GetTLSValue(GlobalParseContextIndex)); +} + diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h b/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h new file mode 100644 index 0000000000..bffbab87d0 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef __INITIALIZE_PARSE_CONTEXT_INCLUDED_ +#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_ + +bool InitializeParseContextIndex(); +void FreeParseContextIndex(); + +struct TParseContext; +extern void SetGlobalParseContext(TParseContext* context); +extern TParseContext* GetGlobalParseContext(); + +#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp new file mode 100644 index 0000000000..115c561c77 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp @@ -0,0 +1,116 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/InitializeVariables.h" +#include "compiler/translator/compilerdebug.h" + +namespace +{ + +TIntermConstantUnion* constructFloatConstUnionNode(const TType& type) +{ + TType myType = type; + unsigned char size = myType.getNominalSize(); + if (myType.isMatrix()) + size *= size; + ConstantUnion *u = new ConstantUnion[size]; + for (int ii = 0; ii < size; ++ii) + u[ii].setFConst(0.0f); + + myType.clearArrayness(); + myType.setQualifier(EvqConst); + TIntermConstantUnion *node = new TIntermConstantUnion(u, myType); + return node; +} + +TIntermConstantUnion* constructIndexNode(int index) +{ + ConstantUnion *u = new ConstantUnion[1]; + u[0].setIConst(index); + + TType type(EbtInt, EbpUndefined, EvqConst, 1); + TIntermConstantUnion *node = new TIntermConstantUnion(u, type); + return node; +} + +} // namespace anonymous + +bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate* node) +{ + bool visitChildren = !mCodeInserted; + switch (node->getOp()) + { + case EOpSequence: + break; + case EOpFunction: + { + // Function definition. + ASSERT(visit == PreVisit); + if (node->getName() == "main(") + { + TIntermSequence &sequence = node->getSequence(); + ASSERT((sequence.size() == 1) || (sequence.size() == 2)); + TIntermAggregate *body = NULL; + if (sequence.size() == 1) + { + body = new TIntermAggregate(EOpSequence); + sequence.push_back(body); + } + else + { + body = sequence[1]->getAsAggregate(); + } + ASSERT(body); + insertInitCode(body->getSequence()); + mCodeInserted = true; + } + break; + } + default: + visitChildren = false; + break; + } + return visitChildren; +} + +void InitializeVariables::insertInitCode(TIntermSequence& sequence) +{ + for (size_t ii = 0; ii < mVariables.size(); ++ii) + { + const InitVariableInfo& varInfo = mVariables[ii]; + + if (varInfo.type.isArray()) + { + for (int index = varInfo.type.getArraySize() - 1; index >= 0; --index) + { + TIntermBinary *assign = new TIntermBinary(EOpAssign); + sequence.insert(sequence.begin(), assign); + + TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect); + TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type); + indexDirect->setLeft(symbol); + TIntermConstantUnion *indexNode = constructIndexNode(index); + indexDirect->setRight(indexNode); + + assign->setLeft(indexDirect); + + TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type); + assign->setRight(zeroConst); + } + } + else + { + TIntermBinary *assign = new TIntermBinary(EOpAssign); + sequence.insert(sequence.begin(), assign); + TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type); + assign->setLeft(symbol); + TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type); + assign->setRight(zeroConst); + } + + } +} + diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h new file mode 100644 index 0000000000..1cd6d7e1b5 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h @@ -0,0 +1,50 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_INITIALIZE_VARIABLES_H_ +#define COMPILER_INITIALIZE_VARIABLES_H_ + +#include "compiler/translator/intermediate.h" + +class InitializeVariables : public TIntermTraverser +{ + public: + struct InitVariableInfo + { + TString name; + TType type; + + InitVariableInfo(const TString& _name, const TType& _type) + : name(_name), + type(_type) + { + } + }; + typedef TVector InitVariableInfoList; + + InitializeVariables(const InitVariableInfoList& vars) + : mCodeInserted(false), + mVariables(vars) + { + } + + protected: + virtual bool visitBinary(Visit visit, TIntermBinary* node) { return false; } + virtual bool visitUnary(Visit visit, TIntermUnary* node) { return false; } + virtual bool visitSelection(Visit visit, TIntermSelection* node) { return false; } + virtual bool visitLoop(Visit visit, TIntermLoop* node) { return false; } + virtual bool visitBranch(Visit visit, TIntermBranch* node) { return false; } + + virtual bool visitAggregate(Visit visit, TIntermAggregate* node); + + private: + void insertInitCode(TIntermSequence& sequence); + + InitVariableInfoList mVariables; + bool mCodeInserted; +}; + +#endif // COMPILER_INITIALIZE_VARIABLES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp new file mode 100644 index 0000000000..554b83409a --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp @@ -0,0 +1,259 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/intermediate.h" + +// +// Traverse the intermediate representation tree, and +// call a node type specific function for each node. +// Done recursively through the member function Traverse(). +// Node types can be skipped if their function to call is 0, +// but their subtree will still be traversed. +// Nodes with children can have their whole subtree skipped +// if preVisit is turned on and the type specific function +// returns false. +// +// preVisit, postVisit, and rightToLeft control what order +// nodes are visited in. +// + +// +// Traversal functions for terminals are straighforward.... +// +void TIntermSymbol::traverse(TIntermTraverser *it) +{ + it->visitSymbol(this); +} + +void TIntermConstantUnion::traverse(TIntermTraverser *it) +{ + it->visitConstantUnion(this); +} + +// +// Traverse a binary node. +// +void TIntermBinary::traverse(TIntermTraverser *it) +{ + bool visit = true; + + // + // visit the node before children if pre-visiting. + // + if (it->preVisit) + visit = it->visitBinary(PreVisit, this); + + // + // Visit the children, in the right order. + // + if (visit) + { + it->incrementDepth(this); + + if (it->rightToLeft) + { + if (right) + right->traverse(it); + + if (it->inVisit) + visit = it->visitBinary(InVisit, this); + + if (visit && left) + left->traverse(it); + } + else + { + if (left) + left->traverse(it); + + if (it->inVisit) + visit = it->visitBinary(InVisit, this); + + if (visit && right) + right->traverse(it); + } + + it->decrementDepth(); + } + + // + // Visit the node after the children, if requested and the traversal + // hasn't been cancelled yet. + // + if (visit && it->postVisit) + it->visitBinary(PostVisit, this); +} + +// +// Traverse a unary node. Same comments in binary node apply here. +// +void TIntermUnary::traverse(TIntermTraverser *it) +{ + bool visit = true; + + if (it->preVisit) + visit = it->visitUnary(PreVisit, this); + + if (visit) { + it->incrementDepth(this); + operand->traverse(it); + it->decrementDepth(); + } + + if (visit && it->postVisit) + it->visitUnary(PostVisit, this); +} + +// +// Traverse an aggregate node. Same comments in binary node apply here. +// +void TIntermAggregate::traverse(TIntermTraverser *it) +{ + bool visit = true; + + if (it->preVisit) + visit = it->visitAggregate(PreVisit, this); + + if (visit) + { + it->incrementDepth(this); + + if (it->rightToLeft) + { + for (TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++) + { + (*sit)->traverse(it); + + if (visit && it->inVisit) + { + if (*sit != sequence.front()) + visit = it->visitAggregate(InVisit, this); + } + } + } + else + { + for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) + { + (*sit)->traverse(it); + + if (visit && it->inVisit) + { + if (*sit != sequence.back()) + visit = it->visitAggregate(InVisit, this); + } + } + } + + it->decrementDepth(); + } + + if (visit && it->postVisit) + it->visitAggregate(PostVisit, this); +} + +// +// Traverse a selection node. Same comments in binary node apply here. +// +void TIntermSelection::traverse(TIntermTraverser *it) +{ + bool visit = true; + + if (it->preVisit) + visit = it->visitSelection(PreVisit, this); + + if (visit) { + it->incrementDepth(this); + if (it->rightToLeft) { + if (falseBlock) + falseBlock->traverse(it); + if (trueBlock) + trueBlock->traverse(it); + condition->traverse(it); + } else { + condition->traverse(it); + if (trueBlock) + trueBlock->traverse(it); + if (falseBlock) + falseBlock->traverse(it); + } + it->decrementDepth(); + } + + if (visit && it->postVisit) + it->visitSelection(PostVisit, this); +} + +// +// Traverse a loop node. Same comments in binary node apply here. +// +void TIntermLoop::traverse(TIntermTraverser *it) +{ + bool visit = true; + + if (it->preVisit) + visit = it->visitLoop(PreVisit, this); + + if (visit) + { + it->incrementDepth(this); + + if (it->rightToLeft) + { + if (expr) + expr->traverse(it); + + if (body) + body->traverse(it); + + if (cond) + cond->traverse(it); + + if (init) + init->traverse(it); + } + else + { + if (init) + init->traverse(it); + + if (cond) + cond->traverse(it); + + if (body) + body->traverse(it); + + if (expr) + expr->traverse(it); + } + + it->decrementDepth(); + } + + if (visit && it->postVisit) + it->visitLoop(PostVisit, this); +} + +// +// Traverse a branch node. Same comments in binary node apply here. +// +void TIntermBranch::traverse(TIntermTraverser *it) +{ + bool visit = true; + + if (it->preVisit) + visit = it->visitBranch(PreVisit, this); + + if (visit && expression) { + it->incrementDepth(this); + expression->traverse(it); + it->decrementDepth(); + } + + if (visit && it->postVisit) + it->visitBranch(PostVisit, this); +} + diff --git a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp new file mode 100644 index 0000000000..777cab5458 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp @@ -0,0 +1,1500 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// +// Build the intermediate representation. +// + +#include +#include +#include + +#include "compiler/translator/HashNames.h" +#include "compiler/translator/localintermediate.h" +#include "compiler/translator/QualifierAlive.h" +#include "compiler/translator/RemoveTree.h" + +bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray); + +static TPrecision GetHigherPrecision(TPrecision left, TPrecision right) +{ + return left > right ? left : right; +} + +const char* getOperatorString(TOperator op) +{ + switch (op) { + case EOpInitialize: return "="; + case EOpAssign: return "="; + case EOpAddAssign: return "+="; + case EOpSubAssign: return "-="; + case EOpDivAssign: return "/="; + + // Fall-through. + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: return "*="; + + // Fall-through. + case EOpIndexDirect: + case EOpIndexIndirect: return "[]"; + + case EOpIndexDirectStruct: return "."; + case EOpVectorSwizzle: return "."; + case EOpAdd: return "+"; + case EOpSub: return "-"; + case EOpMul: return "*"; + case EOpDiv: return "/"; + case EOpMod: UNIMPLEMENTED(); break; + case EOpEqual: return "=="; + case EOpNotEqual: return "!="; + case EOpLessThan: return "<"; + case EOpGreaterThan: return ">"; + case EOpLessThanEqual: return "<="; + case EOpGreaterThanEqual: return ">="; + + // Fall-through. + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpMatrixTimesMatrix: return "*"; + + case EOpLogicalOr: return "||"; + case EOpLogicalXor: return "^^"; + case EOpLogicalAnd: return "&&"; + case EOpNegative: return "-"; + case EOpVectorLogicalNot: return "not"; + case EOpLogicalNot: return "!"; + case EOpPostIncrement: return "++"; + case EOpPostDecrement: return "--"; + case EOpPreIncrement: return "++"; + case EOpPreDecrement: return "--"; + + // Fall-through. + case EOpConvIntToBool: + case EOpConvFloatToBool: return "bool"; + + // Fall-through. + case EOpConvBoolToFloat: + case EOpConvIntToFloat: return "float"; + + // Fall-through. + case EOpConvFloatToInt: + case EOpConvBoolToInt: return "int"; + + case EOpRadians: return "radians"; + case EOpDegrees: return "degrees"; + case EOpSin: return "sin"; + case EOpCos: return "cos"; + case EOpTan: return "tan"; + case EOpAsin: return "asin"; + case EOpAcos: return "acos"; + case EOpAtan: return "atan"; + case EOpExp: return "exp"; + case EOpLog: return "log"; + case EOpExp2: return "exp2"; + case EOpLog2: return "log2"; + case EOpSqrt: return "sqrt"; + case EOpInverseSqrt: return "inversesqrt"; + case EOpAbs: return "abs"; + case EOpSign: return "sign"; + case EOpFloor: return "floor"; + case EOpCeil: return "ceil"; + case EOpFract: return "fract"; + case EOpLength: return "length"; + case EOpNormalize: return "normalize"; + case EOpDFdx: return "dFdx"; + case EOpDFdy: return "dFdy"; + case EOpFwidth: return "fwidth"; + case EOpAny: return "any"; + case EOpAll: return "all"; + + default: break; + } + return ""; +} + +//////////////////////////////////////////////////////////////////////////// +// +// First set of functions are to help build the intermediate representation. +// These functions are not member functions of the nodes. +// They are called from parser productions. +// +///////////////////////////////////////////////////////////////////////////// + +// +// Add a terminal node for an identifier in an expression. +// +// Returns the added node. +// +TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc& line) +{ + TIntermSymbol* node = new TIntermSymbol(id, name, type); + node->setLine(line); + + return node; +} + +// +// Connect two nodes with a new parent that does a binary operation on the nodes. +// +// Returns the added node. +// +TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line, TSymbolTable& symbolTable) +{ + switch (op) { + case EOpEqual: + case EOpNotEqual: + if (left->isArray()) + return 0; + break; + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) { + return 0; + } + break; + case EOpLogicalOr: + case EOpLogicalXor: + case EOpLogicalAnd: + if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) { + return 0; + } + break; + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpMul: + if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) + return 0; + default: break; + } + + // + // First try converting the children to compatible types. + // + if (left->getType().getStruct() && right->getType().getStruct()) { + if (left->getType() != right->getType()) + return 0; + } else { + TIntermTyped* child = addConversion(op, left->getType(), right); + if (child) + right = child; + else { + child = addConversion(op, right->getType(), left); + if (child) + left = child; + else + return 0; + } + } + + // + // Need a new node holding things together then. Make + // one and promote it to the right type. + // + TIntermBinary* node = new TIntermBinary(op); + node->setLine(line); + + node->setLeft(left); + node->setRight(right); + if (!node->promote(infoSink)) + return 0; + + // + // See if we can fold constants. + // + TIntermTyped* typedReturnNode = 0; + TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion(); + TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion(); + if (leftTempConstant && rightTempConstant) { + typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink); + + if (typedReturnNode) + return typedReturnNode; + } + + return node; +} + +// +// Connect two nodes through an assignment. +// +// Returns the added node. +// +TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) +{ + // + // Like adding binary math, except the conversion can only go + // from right to left. + // + TIntermBinary* node = new TIntermBinary(op); + node->setLine(line); + + TIntermTyped* child = addConversion(op, left->getType(), right); + if (child == 0) + return 0; + + node->setLeft(left); + node->setRight(child); + if (! node->promote(infoSink)) + return 0; + + return node; +} + +// +// Connect two nodes through an index operator, where the left node is the base +// of an array or struct, and the right node is a direct or indirect offset. +// +// Returns the added node. +// The caller should set the type of the returned node. +// +TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc& line) +{ + TIntermBinary* node = new TIntermBinary(op); + node->setLine(line); + node->setLeft(base); + node->setRight(index); + + // caller should set the type + + return node; +} + +// +// Add one node as the parent of another that it operates on. +// +// Returns the added node. +// +TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc& line, TSymbolTable& symbolTable) +{ + TIntermUnary* node; + TIntermTyped* child = childNode->getAsTyped(); + + if (child == 0) { + infoSink.info.message(EPrefixInternalError, line, "Bad type in AddUnaryMath"); + return 0; + } + + switch (op) { + case EOpLogicalNot: + if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) { + return 0; + } + break; + + case EOpPostIncrement: + case EOpPreIncrement: + case EOpPostDecrement: + case EOpPreDecrement: + case EOpNegative: + if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) + return 0; + default: break; + } + + // + // Do we need to promote the operand? + // + // Note: Implicit promotions were removed from the language. + // + TBasicType newType = EbtVoid; + switch (op) { + case EOpConstructInt: newType = EbtInt; break; + case EOpConstructBool: newType = EbtBool; break; + case EOpConstructFloat: newType = EbtFloat; break; + default: break; + } + + if (newType != EbtVoid) { + child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary, + child->getNominalSize(), + child->isMatrix(), + child->isArray()), + child); + if (child == 0) + return 0; + } + + // + // For constructors, we are now done, it's all in the conversion. + // + switch (op) { + case EOpConstructInt: + case EOpConstructBool: + case EOpConstructFloat: + return child; + default: break; + } + + TIntermConstantUnion *childTempConstant = 0; + if (child->getAsConstantUnion()) + childTempConstant = child->getAsConstantUnion(); + + // + // Make a new node for the operator. + // + node = new TIntermUnary(op); + node->setLine(line); + node->setOperand(child); + + if (! node->promote(infoSink)) + return 0; + + if (childTempConstant) { + TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink); + + if (newChild) + return newChild; + } + + return node; +} + +// +// This is the safe way to change the operator on an aggregate, as it +// does lots of error checking and fixing. Especially for establishing +// a function call's operation on it's set of parameters. Sequences +// of instructions are also aggregates, but they just direnctly set +// their operator to EOpSequence. +// +// Returns an aggregate node, which could be the one passed in if +// it was already an aggregate but no operator was set. +// +TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc& line) +{ + TIntermAggregate* aggNode; + + // + // Make sure we have an aggregate. If not turn it into one. + // + if (node) { + aggNode = node->getAsAggregate(); + if (aggNode == 0 || aggNode->getOp() != EOpNull) { + // + // Make an aggregate containing this node. + // + aggNode = new TIntermAggregate(); + aggNode->getSequence().push_back(node); + } + } else + aggNode = new TIntermAggregate(); + + // + // Set the operator. + // + aggNode->setOp(op); + aggNode->setLine(line); + + return aggNode; +} + +// +// Convert one type to another. +// +// Returns the node representing the conversion, which could be the same +// node passed in if no conversion was needed. +// +// Return 0 if a conversion can't be done. +// +TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node) +{ + // + // Does the base type allow operation? + // + switch (node->getBasicType()) { + case EbtVoid: + case EbtSampler2D: + case EbtSamplerCube: + return 0; + default: break; + } + + // + // Otherwise, if types are identical, no problem + // + if (type == node->getType()) + return node; + + // + // If one's a structure, then no conversions. + // + if (type.getStruct() || node->getType().getStruct()) + return 0; + + // + // If one's an array, then no conversions. + // + if (type.isArray() || node->getType().isArray()) + return 0; + + TBasicType promoteTo; + + switch (op) { + // + // Explicit conversions + // + case EOpConstructBool: + promoteTo = EbtBool; + break; + case EOpConstructFloat: + promoteTo = EbtFloat; + break; + case EOpConstructInt: + promoteTo = EbtInt; + break; + default: + // + // implicit conversions were removed from the language. + // + if (type.getBasicType() != node->getType().getBasicType()) + return 0; + // + // Size and structure could still differ, but that's + // handled by operator promotion. + // + return node; + } + + if (node->getAsConstantUnion()) { + + return (promoteConstantUnion(promoteTo, node->getAsConstantUnion())); + } else { + + // + // Add a new newNode for the conversion. + // + TIntermUnary* newNode = 0; + + TOperator newOp = EOpNull; + switch (promoteTo) { + case EbtFloat: + switch (node->getBasicType()) { + case EbtInt: newOp = EOpConvIntToFloat; break; + case EbtBool: newOp = EOpConvBoolToFloat; break; + default: + infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); + return 0; + } + break; + case EbtBool: + switch (node->getBasicType()) { + case EbtInt: newOp = EOpConvIntToBool; break; + case EbtFloat: newOp = EOpConvFloatToBool; break; + default: + infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); + return 0; + } + break; + case EbtInt: + switch (node->getBasicType()) { + case EbtBool: newOp = EOpConvBoolToInt; break; + case EbtFloat: newOp = EOpConvFloatToInt; break; + default: + infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); + return 0; + } + break; + default: + infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion type"); + return 0; + } + + TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray()); + newNode = new TIntermUnary(newOp, type); + newNode->setLine(node->getLine()); + newNode->setOperand(node); + + return newNode; + } +} + +// +// Safe way to combine two nodes into an aggregate. Works with null pointers, +// a node that's not a aggregate yet, etc. +// +// Returns the resulting aggregate, unless 0 was passed in for +// both existing nodes. +// +TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& line) +{ + if (left == 0 && right == 0) + return 0; + + TIntermAggregate* aggNode = 0; + if (left) + aggNode = left->getAsAggregate(); + if (!aggNode || aggNode->getOp() != EOpNull) { + aggNode = new TIntermAggregate; + if (left) + aggNode->getSequence().push_back(left); + } + + if (right) + aggNode->getSequence().push_back(right); + + aggNode->setLine(line); + + return aggNode; +} + +// +// Turn an existing node into an aggregate. +// +// Returns an aggregate, unless 0 was passed in for the existing node. +// +TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& line) +{ + if (node == 0) + return 0; + + TIntermAggregate* aggNode = new TIntermAggregate; + aggNode->getSequence().push_back(node); + aggNode->setLine(line); + + return aggNode; +} + +// +// For "if" test nodes. There are three children; a condition, +// a true path, and a false path. The two paths are in the +// nodePair. +// +// Returns the selection node created. +// +TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& line) +{ + // + // For compile time constant selections, prune the code and + // test now. + // + + if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) { + if (cond->getAsConstantUnion()->getBConst(0) == true) + return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL; + else + return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL; + } + + TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2); + node->setLine(line); + + return node; +} + + +TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) +{ + if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) { + return right; + } else { + TIntermTyped *commaAggregate = growAggregate(left, right, line); + commaAggregate->getAsAggregate()->setOp(EOpComma); + commaAggregate->setType(right->getType()); + commaAggregate->getTypePointer()->setQualifier(EvqTemporary); + return commaAggregate; + } +} + +// +// For "?:" test nodes. There are three children; a condition, +// a true path, and a false path. The two paths are specified +// as separate parameters. +// +// Returns the selection node created, or 0 if one could not be. +// +TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& line) +{ + // + // Get compatible types. + // + TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock); + if (child) + falseBlock = child; + else { + child = addConversion(EOpSequence, falseBlock->getType(), trueBlock); + if (child) + trueBlock = child; + else + return 0; + } + + // + // See if all the operands are constant, then fold it otherwise not. + // + + if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) { + if (cond->getAsConstantUnion()->getBConst(0)) + return trueBlock; + else + return falseBlock; + } + + // + // Make a selection node. + // + TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType()); + node->getTypePointer()->setQualifier(EvqTemporary); + node->setLine(line); + + return node; +} + +// +// Constant terminal nodes. Has a union that contains bool, float or int constants +// +// Returns the constant union node created. +// + +TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc& line) +{ + TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t); + node->setLine(line); + + return node; +} + +TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& line) +{ + + TIntermAggregate* node = new TIntermAggregate(EOpSequence); + + node->setLine(line); + TIntermConstantUnion* constIntNode; + TIntermSequence &sequenceVector = node->getSequence(); + ConstantUnion* unionArray; + + for (int i = 0; i < fields.num; i++) { + unionArray = new ConstantUnion[1]; + unionArray->setIConst(fields.offsets[i]); + constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line); + sequenceVector.push_back(constIntNode); + } + + return node; +} + +// +// Create loop nodes. +// +TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc& line) +{ + TIntermNode* node = new TIntermLoop(type, init, cond, expr, body); + node->setLine(line); + + return node; +} + +// +// Add branches. +// +TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& line) +{ + return addBranch(branchOp, 0, line); +} + +TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& line) +{ + TIntermBranch* node = new TIntermBranch(branchOp, expression); + node->setLine(line); + + return node; +} + +// +// This is to be executed once the final root is put on top by the parsing +// process. +// +bool TIntermediate::postProcess(TIntermNode* root) +{ + if (root == 0) + return true; + + // + // First, finish off the top level sequence, if any + // + TIntermAggregate* aggRoot = root->getAsAggregate(); + if (aggRoot && aggRoot->getOp() == EOpNull) + aggRoot->setOp(EOpSequence); + + return true; +} + +// +// This deletes the tree. +// +void TIntermediate::remove(TIntermNode* root) +{ + if (root) + RemoveAllTreeNodes(root); +} + +//////////////////////////////////////////////////////////////// +// +// Member functions of the nodes used for building the tree. +// +//////////////////////////////////////////////////////////////// + +#define REPLACE_IF_IS(node, type, original, replacement) \ + if (node == original) { \ + node = static_cast(replacement); \ + return true; \ + } + +bool TIntermLoop::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(init, TIntermNode, original, replacement); + REPLACE_IF_IS(cond, TIntermTyped, original, replacement); + REPLACE_IF_IS(expr, TIntermTyped, original, replacement); + REPLACE_IF_IS(body, TIntermNode, original, replacement); + return false; +} + +bool TIntermBranch::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(expression, TIntermTyped, original, replacement); + return false; +} + +bool TIntermBinary::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(left, TIntermTyped, original, replacement); + REPLACE_IF_IS(right, TIntermTyped, original, replacement); + return false; +} + +bool TIntermUnary::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(operand, TIntermTyped, original, replacement); + return false; +} + +bool TIntermAggregate::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + for (size_t ii = 0; ii < sequence.size(); ++ii) + { + REPLACE_IF_IS(sequence[ii], TIntermNode, original, replacement); + } + return false; +} + +bool TIntermSelection::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(condition, TIntermTyped, original, replacement); + REPLACE_IF_IS(trueBlock, TIntermNode, original, replacement); + REPLACE_IF_IS(falseBlock, TIntermNode, original, replacement); + return false; +} + +// +// Say whether or not an operation node changes the value of a variable. +// +bool TIntermOperator::isAssignment() const +{ + switch (op) { + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + case EOpAssign: + case EOpAddAssign: + case EOpSubAssign: + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + case EOpDivAssign: + return true; + default: + return false; + } +} + +// +// returns true if the operator is for one of the constructors +// +bool TIntermOperator::isConstructor() const +{ + switch (op) { + case EOpConstructVec2: + case EOpConstructVec3: + case EOpConstructVec4: + case EOpConstructMat2: + case EOpConstructMat3: + case EOpConstructMat4: + case EOpConstructFloat: + case EOpConstructIVec2: + case EOpConstructIVec3: + case EOpConstructIVec4: + case EOpConstructInt: + case EOpConstructBVec2: + case EOpConstructBVec3: + case EOpConstructBVec4: + case EOpConstructBool: + case EOpConstructStruct: + return true; + default: + return false; + } +} + +// +// Make sure the type of a unary operator is appropriate for its +// combination of operation and operand type. +// +// Returns false in nothing makes sense. +// +bool TIntermUnary::promote(TInfoSink&) +{ + switch (op) { + case EOpLogicalNot: + if (operand->getBasicType() != EbtBool) + return false; + break; + case EOpNegative: + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + if (operand->getBasicType() == EbtBool) + return false; + break; + + // operators for built-ins are already type checked against their prototype + case EOpAny: + case EOpAll: + case EOpVectorLogicalNot: + return true; + + default: + if (operand->getBasicType() != EbtFloat) + return false; + } + + setType(operand->getType()); + type.setQualifier(EvqTemporary); + + return true; +} + +// +// Establishes the type of the resultant operation, as well as +// makes the operator the correct one for the operands. +// +// Returns false if operator can't work on operands. +// +bool TIntermBinary::promote(TInfoSink& infoSink) +{ + // This function only handles scalars, vectors, and matrices. + if (left->isArray() || right->isArray()) { + infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operation for arrays"); + return false; + } + + // GLSL ES 2.0 does not support implicit type casting. + // So the basic type should always match. + if (left->getBasicType() != right->getBasicType()) + return false; + + // + // Base assumption: just make the type the same as the left + // operand. Then only deviations from this need be coded. + // + setType(left->getType()); + + // The result gets promoted to the highest precision. + TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision()); + getTypePointer()->setPrecision(higherPrecision); + + // Binary operations results in temporary variables unless both + // operands are const. + if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) { + getTypePointer()->setQualifier(EvqTemporary); + } + + int size = std::max(left->getNominalSize(), right->getNominalSize()); + + // + // All scalars. Code after this test assumes this case is removed! + // + if (size == 1) { + switch (op) { + // + // Promote to conditional + // + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + setType(TType(EbtBool, EbpUndefined)); + break; + + // + // And and Or operate on conditionals + // + case EOpLogicalAnd: + case EOpLogicalOr: + // Both operands must be of type bool. + if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool) + return false; + setType(TType(EbtBool, EbpUndefined)); + break; + + default: + break; + } + return true; + } + + // If we reach here, at least one of the operands is vector or matrix. + // The other operand could be a scalar, vector, or matrix. + // Are the sizes compatible? + // + if (left->getNominalSize() != right->getNominalSize()) { + // If the nominal size of operands do not match: + // One of them must be scalar. + if (left->getNominalSize() != 1 && right->getNominalSize() != 1) + return false; + // Operator cannot be of type pure assignment. + if (op == EOpAssign || op == EOpInitialize) + return false; + } + + // + // Can these two operands be combined? + // + TBasicType basicType = left->getBasicType(); + switch (op) { + case EOpMul: + if (!left->isMatrix() && right->isMatrix()) { + if (left->isVector()) + op = EOpVectorTimesMatrix; + else { + op = EOpMatrixTimesScalar; + setType(TType(basicType, higherPrecision, EvqTemporary, size, true)); + } + } else if (left->isMatrix() && !right->isMatrix()) { + if (right->isVector()) { + op = EOpMatrixTimesVector; + setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); + } else { + op = EOpMatrixTimesScalar; + } + } else if (left->isMatrix() && right->isMatrix()) { + op = EOpMatrixTimesMatrix; + } else if (!left->isMatrix() && !right->isMatrix()) { + if (left->isVector() && right->isVector()) { + // leave as component product + } else if (left->isVector() || right->isVector()) { + op = EOpVectorTimesScalar; + setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); + } + } else { + infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses"); + return false; + } + break; + case EOpMulAssign: + if (!left->isMatrix() && right->isMatrix()) { + if (left->isVector()) + op = EOpVectorTimesMatrixAssign; + else { + return false; + } + } else if (left->isMatrix() && !right->isMatrix()) { + if (right->isVector()) { + return false; + } else { + op = EOpMatrixTimesScalarAssign; + } + } else if (left->isMatrix() && right->isMatrix()) { + op = EOpMatrixTimesMatrixAssign; + } else if (!left->isMatrix() && !right->isMatrix()) { + if (left->isVector() && right->isVector()) { + // leave as component product + } else if (left->isVector() || right->isVector()) { + if (! left->isVector()) + return false; + op = EOpVectorTimesScalarAssign; + setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); + } + } else { + infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses"); + return false; + } + break; + + case EOpAssign: + case EOpInitialize: + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpAddAssign: + case EOpSubAssign: + case EOpDivAssign: + if ((left->isMatrix() && right->isVector()) || + (left->isVector() && right->isMatrix())) + return false; + setType(TType(basicType, higherPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix())); + break; + + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + if ((left->isMatrix() && right->isVector()) || + (left->isVector() && right->isMatrix())) + return false; + setType(TType(EbtBool, EbpUndefined)); + break; + + default: + return false; + } + + return true; +} + +bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) +{ + const TFieldList& fields = leftNodeType.getStruct()->fields(); + + size_t structSize = fields.size(); + size_t index = 0; + + for (size_t j = 0; j < structSize; j++) { + size_t size = fields[j]->type()->getObjectSize(); + for (size_t i = 0; i < size; i++) { + if (fields[j]->type()->getBasicType() == EbtStruct) { + if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index])) + return false; + } else { + if (leftUnionArray[index] != rightUnionArray[index]) + return false; + index++; + } + } + } + return true; +} + +bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) +{ + if (leftNodeType.isArray()) { + TType typeWithoutArrayness = leftNodeType; + typeWithoutArrayness.clearArrayness(); + + size_t arraySize = leftNodeType.getArraySize(); + + for (size_t i = 0; i < arraySize; ++i) { + size_t offset = typeWithoutArrayness.getObjectSize() * i; + if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset])) + return false; + } + } else + return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray); + + return true; +} + +// +// The fold functions see if an operation on a constant can be done in place, +// without generating run-time code. +// +// Returns the node to keep using, which may or may not be the node passed in. +// + +TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink) +{ + ConstantUnion *unionArray = getUnionArrayPointer(); + size_t objectSize = getType().getObjectSize(); + + if (constantNode) { // binary operations + TIntermConstantUnion *node = constantNode->getAsConstantUnion(); + ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); + TType returnType = getType(); + + // for a case like float f = 1.2 + vec4(2,3,4,5); + if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) { + rightUnionArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; ++i) + rightUnionArray[i] = *node->getUnionArrayPointer(); + returnType = getType(); + } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) { + // for a case like float f = vec4(2,3,4,5) + 1.2; + unionArray = new ConstantUnion[constantNode->getType().getObjectSize()]; + for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i) + unionArray[i] = *getUnionArrayPointer(); + returnType = node->getType(); + objectSize = constantNode->getType().getObjectSize(); + } + + ConstantUnion* tempConstArray = 0; + TIntermConstantUnion *tempNode; + + bool boolNodeFlag = false; + switch(op) { + case EOpAdd: + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] + rightUnionArray[i]; + } + break; + case EOpSub: + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] - rightUnionArray[i]; + } + break; + + case EOpMul: + case EOpVectorTimesScalar: + case EOpMatrixTimesScalar: + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] * rightUnionArray[i]; + } + break; + case EOpMatrixTimesMatrix: + if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) { + infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix multiply"); + return 0; + } + {// support MSVC++6.0 + int size = getNominalSize(); + tempConstArray = new ConstantUnion[size*size]; + for (int row = 0; row < size; row++) { + for (int column = 0; column < size; column++) { + tempConstArray[size * column + row].setFConst(0.0f); + for (int i = 0; i < size; i++) { + tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst())); + } + } + } + } + break; + case EOpDiv: + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (size_t i = 0; i < objectSize; i++) { + switch (getType().getBasicType()) { + case EbtFloat: + if (rightUnionArray[i] == 0.0f) { + infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding"); + tempConstArray[i].setFConst(unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX); + } else + tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst()); + break; + + case EbtInt: + if (rightUnionArray[i] == 0) { + infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding"); + tempConstArray[i].setIConst(INT_MAX); + } else + tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst()); + break; + default: + infoSink.info.message(EPrefixInternalError, getLine(), "Constant folding cannot be done for \"/\""); + return 0; + } + } + } + break; + + case EOpMatrixTimesVector: + if (node->getBasicType() != EbtFloat) { + infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix times vector"); + return 0; + } + tempConstArray = new ConstantUnion[getNominalSize()]; + + {// support MSVC++6.0 + for (int size = getNominalSize(), i = 0; i < size; i++) { + tempConstArray[i].setFConst(0.0f); + for (int j = 0; j < size; j++) { + tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst())); + } + } + } + + tempNode = new TIntermConstantUnion(tempConstArray, node->getType()); + tempNode->setLine(getLine()); + + return tempNode; + + case EOpVectorTimesMatrix: + if (getType().getBasicType() != EbtFloat) { + infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for vector times matrix"); + return 0; + } + + tempConstArray = new ConstantUnion[getNominalSize()]; + {// support MSVC++6.0 + for (int size = getNominalSize(), i = 0; i < size; i++) { + tempConstArray[i].setFConst(0.0f); + for (int j = 0; j < size; j++) { + tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst())); + } + } + } + break; + + case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] && rightUnionArray[i]; + } + break; + + case EOpLogicalOr: // this code is written for possible future use, will not get executed currently + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] || rightUnionArray[i]; + } + break; + + case EOpLogicalXor: + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (size_t i = 0; i < objectSize; i++) + switch (getType().getBasicType()) { + case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break; + default: assert(false && "Default missing"); + } + } + break; + + case EOpLessThan: + assert(objectSize == 1); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(*unionArray < *rightUnionArray); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + case EOpGreaterThan: + assert(objectSize == 1); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(*unionArray > *rightUnionArray); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + case EOpLessThanEqual: + { + assert(objectSize == 1); + ConstantUnion constant; + constant.setBConst(*unionArray > *rightUnionArray); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(!constant.getBConst()); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + } + case EOpGreaterThanEqual: + { + assert(objectSize == 1); + ConstantUnion constant; + constant.setBConst(*unionArray < *rightUnionArray); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(!constant.getBConst()); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + } + + case EOpEqual: + if (getType().getBasicType() == EbtStruct) { + if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) + boolNodeFlag = true; + } else { + for (size_t i = 0; i < objectSize; i++) { + if (unionArray[i] != rightUnionArray[i]) { + boolNodeFlag = true; + break; // break out of for loop + } + } + } + + tempConstArray = new ConstantUnion[1]; + if (!boolNodeFlag) { + tempConstArray->setBConst(true); + } + else { + tempConstArray->setBConst(false); + } + + tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); + tempNode->setLine(getLine()); + + return tempNode; + + case EOpNotEqual: + if (getType().getBasicType() == EbtStruct) { + if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) + boolNodeFlag = true; + } else { + for (size_t i = 0; i < objectSize; i++) { + if (unionArray[i] == rightUnionArray[i]) { + boolNodeFlag = true; + break; // break out of for loop + } + } + } + + tempConstArray = new ConstantUnion[1]; + if (!boolNodeFlag) { + tempConstArray->setBConst(true); + } + else { + tempConstArray->setBConst(false); + } + + tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); + tempNode->setLine(getLine()); + + return tempNode; + + default: + infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operator for constant folding"); + return 0; + } + tempNode = new TIntermConstantUnion(tempConstArray, returnType); + tempNode->setLine(getLine()); + + return tempNode; + } else { + // + // Do unary operations + // + TIntermConstantUnion *newNode = 0; + ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) { + switch(op) { + case EOpNegative: + switch (getType().getBasicType()) { + case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break; + case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break; + default: + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return 0; + } + break; + case EOpLogicalNot: // this code is written for possible future use, will not get executed currently + switch (getType().getBasicType()) { + case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break; + default: + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return 0; + } + break; + default: + return 0; + } + } + newNode = new TIntermConstantUnion(tempConstArray, getType()); + newNode->setLine(getLine()); + return newNode; + } +} + +TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) +{ + size_t size = node->getType().getObjectSize(); + + ConstantUnion *leftUnionArray = new ConstantUnion[size]; + + for (size_t i = 0; i < size; i++) { + + switch (promoteTo) { + case EbtFloat: + switch (node->getType().getBasicType()) { + case EbtInt: + leftUnionArray[i].setFConst(static_cast(node->getIConst(i))); + break; + case EbtBool: + leftUnionArray[i].setFConst(static_cast(node->getBConst(i))); + break; + case EbtFloat: + leftUnionArray[i].setFConst(static_cast(node->getFConst(i))); + break; + default: + infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); + return 0; + } + break; + case EbtInt: + switch (node->getType().getBasicType()) { + case EbtInt: + leftUnionArray[i].setIConst(static_cast(node->getIConst(i))); + break; + case EbtBool: + leftUnionArray[i].setIConst(static_cast(node->getBConst(i))); + break; + case EbtFloat: + leftUnionArray[i].setIConst(static_cast(node->getFConst(i))); + break; + default: + infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); + return 0; + } + break; + case EbtBool: + switch (node->getType().getBasicType()) { + case EbtInt: + leftUnionArray[i].setBConst(node->getIConst(i) != 0); + break; + case EbtBool: + leftUnionArray[i].setBConst(node->getBConst(i)); + break; + case EbtFloat: + leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f); + break; + default: + infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); + return 0; + } + + break; + default: + infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found"); + return 0; + } + + } + + const TType& t = node->getType(); + + return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine()); +} + +// static +TString TIntermTraverser::hash(const TString& name, ShHashFunction64 hashFunction) +{ + if (hashFunction == NULL || name.empty()) + return name; + khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length()); + TStringStream stream; + stream << HASHED_NAME_PREFIX << std::hex << number; + TString hashedName = stream.str(); + return hashedName; +} diff --git a/src/3rdparty/angle/src/compiler/translator/MMap.h b/src/3rdparty/angle/src/compiler/translator/MMap.h new file mode 100644 index 0000000000..a308671514 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/MMap.h @@ -0,0 +1,56 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _MMAP_INCLUDED_ +#define _MMAP_INCLUDED_ + +// +// Encapsulate memory mapped files +// + +class TMMap { +public: + TMMap(const char* fileName) : + fSize(-1), // -1 is the error value returned by GetFileSize() + fp(NULL), + fBuff(0) // 0 is the error value returned by MapViewOfFile() + { + if ((fp = fopen(fileName, "r")) == NULL) + return; + char c = getc(fp); + fSize = 0; + while (c != EOF) { + fSize++; + c = getc(fp); + } + if (c == EOF) + fSize++; + rewind(fp); + fBuff = (char*)malloc(sizeof(char) * fSize); + int count = 0; + c = getc(fp); + while (c != EOF) { + fBuff[count++] = c; + c = getc(fp); + } + fBuff[count++] = c; + } + + char* getData() { return fBuff; } + int getSize() { return fSize; } + + ~TMMap() { + if (fp != NULL) + fclose(fp); + } + +private: + int fSize; // size of file to map in + FILE *fp; + char* fBuff; // the actual data; +}; + +#endif // _MMAP_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.cpp b/src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.cpp new file mode 100644 index 0000000000..ef629c26b1 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.cpp @@ -0,0 +1,115 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/MapLongVariableNames.h" + +namespace { + +TString mapLongName(size_t id, const TString& name, bool isGlobal) +{ + ASSERT(name.size() > MAX_SHORTENED_IDENTIFIER_SIZE); + TStringStream stream; + stream << "webgl_"; + if (isGlobal) + stream << "g"; + stream << id; + if (name[0] != '_') + stream << "_"; + stream << name.substr(0, MAX_SHORTENED_IDENTIFIER_SIZE - stream.str().size()); + return stream.str(); +} + +LongNameMap* gLongNameMapInstance = NULL; + +} // anonymous namespace + +LongNameMap::LongNameMap() + : refCount(0) +{ +} + +LongNameMap::~LongNameMap() +{ +} + +// static +LongNameMap* LongNameMap::GetInstance() +{ + if (gLongNameMapInstance == NULL) + gLongNameMapInstance = new LongNameMap; + gLongNameMapInstance->refCount++; + return gLongNameMapInstance; +} + +void LongNameMap::Release() +{ + ASSERT(gLongNameMapInstance == this); + ASSERT(refCount > 0); + refCount--; + if (refCount == 0) { + delete gLongNameMapInstance; + gLongNameMapInstance = NULL; + } +} + +const char* LongNameMap::Find(const char* originalName) const +{ + std::map::const_iterator it = mLongNameMap.find( + originalName); + if (it != mLongNameMap.end()) + return (*it).second.c_str(); + return NULL; +} + +void LongNameMap::Insert(const char* originalName, const char* mappedName) +{ + mLongNameMap.insert(std::map::value_type( + originalName, mappedName)); +} + +size_t LongNameMap::Size() const +{ + return mLongNameMap.size(); +} + +MapLongVariableNames::MapLongVariableNames(LongNameMap* globalMap) +{ + ASSERT(globalMap); + mGlobalMap = globalMap; +} + +void MapLongVariableNames::visitSymbol(TIntermSymbol* symbol) +{ + ASSERT(symbol != NULL); + if (symbol->getSymbol().size() > MAX_SHORTENED_IDENTIFIER_SIZE) { + switch (symbol->getQualifier()) { + case EvqVaryingIn: + case EvqVaryingOut: + case EvqInvariantVaryingIn: + case EvqInvariantVaryingOut: + case EvqUniform: + symbol->setSymbol( + mapGlobalLongName(symbol->getSymbol())); + break; + default: + symbol->setSymbol( + mapLongName(symbol->getId(), symbol->getSymbol(), false)); + break; + }; + } +} + +TString MapLongVariableNames::mapGlobalLongName(const TString& name) +{ + ASSERT(mGlobalMap); + const char* mappedName = mGlobalMap->Find(name.c_str()); + if (mappedName != NULL) + return mappedName; + size_t id = mGlobalMap->Size(); + TString rt = mapLongName(id, name, true); + mGlobalMap->Insert(name.c_str(), rt.c_str()); + return rt; +} diff --git a/src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.h b/src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.h new file mode 100644 index 0000000000..3b085a3687 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.h @@ -0,0 +1,58 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_MAP_LONG_VARIABLE_NAMES_H_ +#define COMPILER_MAP_LONG_VARIABLE_NAMES_H_ + +#include "GLSLANG/ShaderLang.h" + +#include "compiler/translator/intermediate.h" +#include "compiler/translator/VariableInfo.h" + +// This size does not include '\0' in the end. +#define MAX_SHORTENED_IDENTIFIER_SIZE 32 + +// This is a ref-counted singleton. GetInstance() returns a pointer to the +// singleton, and after use, call Release(). GetInstance() and Release() should +// be paired. +class LongNameMap { +public: + static LongNameMap* GetInstance(); + void Release(); + + // Return the mapped name if is in the map; + // otherwise, return NULL. + const char* Find(const char* originalName) const; + + // Insert a pair into the map. + void Insert(const char* originalName, const char* mappedName); + + // Return the number of entries in the map. + size_t Size() const; + +private: + LongNameMap(); + ~LongNameMap(); + + size_t refCount; + std::map mLongNameMap; +}; + +// Traverses intermediate tree to map attributes and uniforms names that are +// longer than MAX_SHORTENED_IDENTIFIER_SIZE to MAX_SHORTENED_IDENTIFIER_SIZE. +class MapLongVariableNames : public TIntermTraverser { +public: + MapLongVariableNames(LongNameMap* globalMap); + + virtual void visitSymbol(TIntermSymbol*); + +private: + TString mapGlobalLongName(const TString& name); + + LongNameMap* mGlobalMap; +}; + +#endif // COMPILER_MAP_LONG_VARIABLE_NAMES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h new file mode 100644 index 0000000000..b58c7ec689 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h @@ -0,0 +1,80 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// NodeSearch.h: Utilities for searching translator node graphs +// + +#ifndef TRANSLATOR_NODESEARCH_H_ +#define TRANSLATOR_NODESEARCH_H_ + +#include "compiler/translator/intermediate.h" + +namespace sh +{ + +template +class NodeSearchTraverser : public TIntermTraverser +{ + public: + NodeSearchTraverser() + : mFound(false) + {} + + bool found() const { return mFound; } + + static bool search(TIntermNode *node) + { + Parent searchTraverser; + node->traverse(&searchTraverser); + return searchTraverser.found(); + } + + protected: + bool mFound; +}; + +class FindDiscard : public NodeSearchTraverser +{ + public: + virtual bool visitBranch(Visit visit, TIntermBranch *node) + { + switch (node->getFlowOp()) + { + case EOpKill: + mFound = true; + break; + + default: break; + } + + return !mFound; + } +}; + +class FindSideEffectRewriting : public NodeSearchTraverser +{ + public: + virtual bool visitBinary(Visit visit, TIntermBinary *node) + { + switch (node->getOp()) + { + case EOpLogicalOr: + case EOpLogicalAnd: + if (node->getRight()->hasSideEffects()) + { + mFound = true; + } + break; + + default: break; + } + + return !mFound; + } +}; + +} + +#endif // TRANSLATOR_NODESEARCH_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp new file mode 100644 index 0000000000..8367412462 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp @@ -0,0 +1,26 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/OutputESSL.h" + +TOutputESSL::TOutputESSL(TInfoSinkBase& objSink, + ShArrayIndexClampingStrategy clampingStrategy, + ShHashFunction64 hashFunction, + NameMap& nameMap, + TSymbolTable& symbolTable) + : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable) +{ +} + +bool TOutputESSL::writeVariablePrecision(TPrecision precision) +{ + if (precision == EbpUndefined) + return false; + + TInfoSinkBase& out = objSink(); + out << getPrecisionString(precision); + return true; +} diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.h b/src/3rdparty/angle/src/compiler/translator/OutputESSL.h new file mode 100644 index 0000000000..2f02979a05 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/OutputESSL.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef CROSSCOMPILERGLSL_OUTPUTESSL_H_ +#define CROSSCOMPILERGLSL_OUTPUTESSL_H_ + +#include "compiler/translator/OutputGLSLBase.h" + +class TOutputESSL : public TOutputGLSLBase +{ +public: + TOutputESSL(TInfoSinkBase& objSink, + ShArrayIndexClampingStrategy clampingStrategy, + ShHashFunction64 hashFunction, + NameMap& nameMap, + TSymbolTable& symbolTable); + +protected: + virtual bool writeVariablePrecision(TPrecision precision); +}; + +#endif // CROSSCOMPILERGLSL_OUTPUTESSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp new file mode 100644 index 0000000000..5589560682 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp @@ -0,0 +1,35 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/OutputGLSL.h" + +TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink, + ShArrayIndexClampingStrategy clampingStrategy, + ShHashFunction64 hashFunction, + NameMap& nameMap, + TSymbolTable& symbolTable) + : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable) +{ +} + +bool TOutputGLSL::writeVariablePrecision(TPrecision) +{ + return false; +} + +void TOutputGLSL::visitSymbol(TIntermSymbol* node) +{ + TInfoSinkBase& out = objSink(); + + if (node->getSymbol() == "gl_FragDepthEXT") + { + out << "gl_FragDepth"; + } + else + { + TOutputGLSLBase::visitSymbol(node); + } +} diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h new file mode 100644 index 0000000000..e1f114d347 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h @@ -0,0 +1,26 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef CROSSCOMPILERGLSL_OUTPUTGLSL_H_ +#define CROSSCOMPILERGLSL_OUTPUTGLSL_H_ + +#include "compiler/translator/OutputGLSLBase.h" + +class TOutputGLSL : public TOutputGLSLBase +{ +public: + TOutputGLSL(TInfoSinkBase& objSink, + ShArrayIndexClampingStrategy clampingStrategy, + ShHashFunction64 hashFunction, + NameMap& nameMap, + TSymbolTable& symbolTable); + +protected: + virtual bool writeVariablePrecision(TPrecision); + virtual void visitSymbol(TIntermSymbol* node); +}; + +#endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp new file mode 100644 index 0000000000..f2f0a3d6be --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp @@ -0,0 +1,817 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/OutputGLSLBase.h" +#include "compiler/translator/compilerdebug.h" + +#include + +namespace +{ +TString arrayBrackets(const TType& type) +{ + ASSERT(type.isArray()); + TInfoSinkBase out; + out << "[" << type.getArraySize() << "]"; + return TString(out.c_str()); +} + +bool isSingleStatement(TIntermNode* node) { + if (const TIntermAggregate* aggregate = node->getAsAggregate()) + { + return (aggregate->getOp() != EOpFunction) && + (aggregate->getOp() != EOpSequence); + } + else if (const TIntermSelection* selection = node->getAsSelectionNode()) + { + // Ternary operators are usually part of an assignment operator. + // This handles those rare cases in which they are all by themselves. + return selection->usesTernaryOperator(); + } + else if (node->getAsLoopNode()) + { + return false; + } + return true; +} +} // namespace + +TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink, + ShArrayIndexClampingStrategy clampingStrategy, + ShHashFunction64 hashFunction, + NameMap& nameMap, + TSymbolTable& symbolTable) + : TIntermTraverser(true, true, true), + mObjSink(objSink), + mDeclaringVariables(false), + mClampingStrategy(clampingStrategy), + mHashFunction(hashFunction), + mNameMap(nameMap), + mSymbolTable(symbolTable) +{ +} + +void TOutputGLSLBase::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr) +{ + TInfoSinkBase& out = objSink(); + if (visit == PreVisit && preStr) + { + out << preStr; + } + else if (visit == InVisit && inStr) + { + out << inStr; + } + else if (visit == PostVisit && postStr) + { + out << postStr; + } +} + +void TOutputGLSLBase::writeVariableType(const TType& type) +{ + TInfoSinkBase& out = objSink(); + TQualifier qualifier = type.getQualifier(); + // TODO(alokp): Validate qualifier for variable declarations. + if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal)) + out << type.getQualifierString() << " "; + // Declare the struct if we have not done so already. + if ((type.getBasicType() == EbtStruct) && !structDeclared(type.getStruct())) + { + declareStruct(type.getStruct()); + } + else + { + if (writeVariablePrecision(type.getPrecision())) + out << " "; + out << getTypeName(type); + } +} + +void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence& args) +{ + TInfoSinkBase& out = objSink(); + for (TIntermSequence::const_iterator iter = args.begin(); + iter != args.end(); ++iter) + { + const TIntermSymbol* arg = (*iter)->getAsSymbolNode(); + ASSERT(arg != NULL); + + const TType& type = arg->getType(); + writeVariableType(type); + + const TString& name = arg->getSymbol(); + if (!name.empty()) + out << " " << hashName(name); + if (type.isArray()) + out << arrayBrackets(type); + + // Put a comma if this is not the last argument. + if (iter != args.end() - 1) + out << ", "; + } +} + +const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type, + const ConstantUnion* pConstUnion) +{ + TInfoSinkBase& out = objSink(); + + if (type.getBasicType() == EbtStruct) + { + const TStructure* structure = type.getStruct(); + out << hashName(structure->name()) << "("; + + const TFieldList& fields = structure->fields(); + for (size_t i = 0; i < fields.size(); ++i) + { + const TType* fieldType = fields[i]->type(); + ASSERT(fieldType != NULL); + pConstUnion = writeConstantUnion(*fieldType, pConstUnion); + if (i != fields.size() - 1) out << ", "; + } + out << ")"; + } + else + { + size_t size = type.getObjectSize(); + bool writeType = size > 1; + if (writeType) out << getTypeName(type) << "("; + for (size_t i = 0; i < size; ++i, ++pConstUnion) + { + switch (pConstUnion->getType()) + { + case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, pConstUnion->getFConst())); break; + case EbtInt: out << pConstUnion->getIConst(); break; + case EbtBool: out << pConstUnion->getBConst(); break; + default: UNREACHABLE(); + } + if (i != size - 1) out << ", "; + } + if (writeType) out << ")"; + } + return pConstUnion; +} + +void TOutputGLSLBase::visitSymbol(TIntermSymbol* node) +{ + TInfoSinkBase& out = objSink(); + if (mLoopUnroll.NeedsToReplaceSymbolWithValue(node)) + out << mLoopUnroll.GetLoopIndexValue(node); + else + out << hashVariableName(node->getSymbol()); + + if (mDeclaringVariables && node->getType().isArray()) + out << arrayBrackets(node->getType()); +} + +void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion* node) +{ + writeConstantUnion(node->getType(), node->getUnionArrayPointer()); +} + +bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node) +{ + bool visitChildren = true; + TInfoSinkBase& out = objSink(); + switch (node->getOp()) + { + case EOpInitialize: + if (visit == InVisit) + { + out << " = "; + // RHS of initialize is not being declared. + mDeclaringVariables = false; + } + break; + case EOpAssign: writeTriplet(visit, "(", " = ", ")"); break; + case EOpAddAssign: writeTriplet(visit, "(", " += ", ")"); break; + case EOpSubAssign: writeTriplet(visit, "(", " -= ", ")"); break; + case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break; + // Notice the fall-through. + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + writeTriplet(visit, "(", " *= ", ")"); + break; + + case EOpIndexDirect: + writeTriplet(visit, NULL, "[", "]"); + break; + case EOpIndexIndirect: + if (node->getAddIndexClamp()) + { + if (visit == InVisit) + { + if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) { + out << "[int(clamp(float("; + } else { + out << "[webgl_int_clamp("; + } + } + else if (visit == PostVisit) + { + int maxSize; + TIntermTyped *left = node->getLeft(); + TType leftType = left->getType(); + + if (left->isArray()) + { + // The shader will fail validation if the array length is not > 0. + maxSize = leftType.getArraySize() - 1; + } + else + { + maxSize = leftType.getNominalSize() - 1; + } + + if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) { + out << "), 0.0, float(" << maxSize << ")))]"; + } else { + out << ", 0, " << maxSize << ")]"; + } + } + } + else + { + writeTriplet(visit, NULL, "[", "]"); + } + break; + case EOpIndexDirectStruct: + if (visit == InVisit) + { + // Here we are writing out "foo.bar", where "foo" is struct + // and "bar" is field. In AST, it is represented as a binary + // node, where left child represents "foo" and right child "bar". + // The node itself represents ".". The struct field "bar" is + // actually stored as an index into TStructure::fields. + out << "."; + const TStructure* structure = node->getLeft()->getType().getStruct(); + const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion(); + const TField* field = structure->fields()[index->getIConst(0)]; + + TString fieldName = field->name(); + if (!mSymbolTable.findBuiltIn(structure->name())) + fieldName = hashName(fieldName); + + out << fieldName; + visitChildren = false; + } + break; + case EOpVectorSwizzle: + if (visit == InVisit) + { + out << "."; + TIntermAggregate* rightChild = node->getRight()->getAsAggregate(); + TIntermSequence& sequence = rightChild->getSequence(); + for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit) + { + TIntermConstantUnion* element = (*sit)->getAsConstantUnion(); + ASSERT(element->getBasicType() == EbtInt); + ASSERT(element->getNominalSize() == 1); + const ConstantUnion& data = element->getUnionArrayPointer()[0]; + ASSERT(data.getType() == EbtInt); + switch (data.getIConst()) + { + case 0: out << "x"; break; + case 1: out << "y"; break; + case 2: out << "z"; break; + case 3: out << "w"; break; + default: UNREACHABLE(); break; + } + } + visitChildren = false; + } + break; + + case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break; + case EOpSub: writeTriplet(visit, "(", " - ", ")"); break; + case EOpMul: writeTriplet(visit, "(", " * ", ")"); break; + case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break; + case EOpMod: UNIMPLEMENTED(); break; + case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break; + case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break; + case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break; + case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break; + case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break; + case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break; + + // Notice the fall-through. + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpMatrixTimesMatrix: + writeTriplet(visit, "(", " * ", ")"); + break; + + case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break; + case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break; + case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break; + default: UNREACHABLE(); break; + } + + return visitChildren; +} + +bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node) +{ + TString preString; + TString postString = ")"; + + switch (node->getOp()) + { + case EOpNegative: preString = "(-"; break; + case EOpVectorLogicalNot: preString = "not("; break; + case EOpLogicalNot: preString = "(!"; break; + + case EOpPostIncrement: preString = "("; postString = "++)"; break; + case EOpPostDecrement: preString = "("; postString = "--)"; break; + case EOpPreIncrement: preString = "(++"; break; + case EOpPreDecrement: preString = "(--"; break; + + case EOpConvIntToBool: + case EOpConvFloatToBool: + switch (node->getOperand()->getType().getNominalSize()) + { + case 1: preString = "bool("; break; + case 2: preString = "bvec2("; break; + case 3: preString = "bvec3("; break; + case 4: preString = "bvec4("; break; + default: UNREACHABLE(); + } + break; + case EOpConvBoolToFloat: + case EOpConvIntToFloat: + switch (node->getOperand()->getType().getNominalSize()) + { + case 1: preString = "float("; break; + case 2: preString = "vec2("; break; + case 3: preString = "vec3("; break; + case 4: preString = "vec4("; break; + default: UNREACHABLE(); + } + break; + case EOpConvFloatToInt: + case EOpConvBoolToInt: + switch (node->getOperand()->getType().getNominalSize()) + { + case 1: preString = "int("; break; + case 2: preString = "ivec2("; break; + case 3: preString = "ivec3("; break; + case 4: preString = "ivec4("; break; + default: UNREACHABLE(); + } + break; + + case EOpRadians: preString = "radians("; break; + case EOpDegrees: preString = "degrees("; break; + case EOpSin: preString = "sin("; break; + case EOpCos: preString = "cos("; break; + case EOpTan: preString = "tan("; break; + case EOpAsin: preString = "asin("; break; + case EOpAcos: preString = "acos("; break; + case EOpAtan: preString = "atan("; break; + + case EOpExp: preString = "exp("; break; + case EOpLog: preString = "log("; break; + case EOpExp2: preString = "exp2("; break; + case EOpLog2: preString = "log2("; break; + case EOpSqrt: preString = "sqrt("; break; + case EOpInverseSqrt: preString = "inversesqrt("; break; + + case EOpAbs: preString = "abs("; break; + case EOpSign: preString = "sign("; break; + case EOpFloor: preString = "floor("; break; + case EOpCeil: preString = "ceil("; break; + case EOpFract: preString = "fract("; break; + + case EOpLength: preString = "length("; break; + case EOpNormalize: preString = "normalize("; break; + + case EOpDFdx: preString = "dFdx("; break; + case EOpDFdy: preString = "dFdy("; break; + case EOpFwidth: preString = "fwidth("; break; + + case EOpAny: preString = "any("; break; + case EOpAll: preString = "all("; break; + + default: UNREACHABLE(); break; + } + + if (visit == PreVisit && node->getUseEmulatedFunction()) + preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString); + writeTriplet(visit, preString.c_str(), NULL, postString.c_str()); + + return true; +} + +bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection* node) +{ + TInfoSinkBase& out = objSink(); + + if (node->usesTernaryOperator()) + { + // Notice two brackets at the beginning and end. The outer ones + // encapsulate the whole ternary expression. This preserves the + // order of precedence when ternary expressions are used in a + // compound expression, i.e., c = 2 * (a < b ? 1 : 2). + out << "(("; + node->getCondition()->traverse(this); + out << ") ? ("; + node->getTrueBlock()->traverse(this); + out << ") : ("; + node->getFalseBlock()->traverse(this); + out << "))"; + } + else + { + out << "if ("; + node->getCondition()->traverse(this); + out << ")\n"; + + incrementDepth(node); + visitCodeBlock(node->getTrueBlock()); + + if (node->getFalseBlock()) + { + out << "else\n"; + visitCodeBlock(node->getFalseBlock()); + } + decrementDepth(); + } + return false; +} + +bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) +{ + bool visitChildren = true; + TInfoSinkBase& out = objSink(); + TString preString; + bool delayedWrite = false; + switch (node->getOp()) + { + case EOpSequence: { + // Scope the sequences except when at the global scope. + if (depth > 0) out << "{\n"; + + incrementDepth(node); + const TIntermSequence& sequence = node->getSequence(); + for (TIntermSequence::const_iterator iter = sequence.begin(); + iter != sequence.end(); ++iter) + { + TIntermNode* node = *iter; + ASSERT(node != NULL); + node->traverse(this); + + if (isSingleStatement(node)) + out << ";\n"; + } + decrementDepth(); + + // Scope the sequences except when at the global scope. + if (depth > 0) out << "}\n"; + visitChildren = false; + break; + } + case EOpPrototype: { + // Function declaration. + ASSERT(visit == PreVisit); + writeVariableType(node->getType()); + out << " " << hashName(node->getName()); + + out << "("; + writeFunctionParameters(node->getSequence()); + out << ")"; + + visitChildren = false; + break; + } + case EOpFunction: { + // Function definition. + ASSERT(visit == PreVisit); + writeVariableType(node->getType()); + out << " " << hashFunctionName(node->getName()); + + incrementDepth(node); + // Function definition node contains one or two children nodes + // representing function parameters and function body. The latter + // is not present in case of empty function bodies. + const TIntermSequence& sequence = node->getSequence(); + ASSERT((sequence.size() == 1) || (sequence.size() == 2)); + TIntermSequence::const_iterator seqIter = sequence.begin(); + + // Traverse function parameters. + TIntermAggregate* params = (*seqIter)->getAsAggregate(); + ASSERT(params != NULL); + ASSERT(params->getOp() == EOpParameters); + params->traverse(this); + + // Traverse function body. + TIntermAggregate* body = ++seqIter != sequence.end() ? + (*seqIter)->getAsAggregate() : NULL; + visitCodeBlock(body); + decrementDepth(); + + // Fully processed; no need to visit children. + visitChildren = false; + break; + } + case EOpFunctionCall: + // Function call. + if (visit == PreVisit) + { + out << hashFunctionName(node->getName()) << "("; + } + else if (visit == InVisit) + { + out << ", "; + } + else + { + out << ")"; + } + break; + case EOpParameters: { + // Function parameters. + ASSERT(visit == PreVisit); + out << "("; + writeFunctionParameters(node->getSequence()); + out << ")"; + visitChildren = false; + break; + } + case EOpDeclaration: { + // Variable declaration. + if (visit == PreVisit) + { + const TIntermSequence& sequence = node->getSequence(); + const TIntermTyped* variable = sequence.front()->getAsTyped(); + writeVariableType(variable->getType()); + out << " "; + mDeclaringVariables = true; + } + else if (visit == InVisit) + { + out << ", "; + mDeclaringVariables = true; + } + else + { + mDeclaringVariables = false; + } + break; + } + case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break; + case EOpConstructVec2: writeTriplet(visit, "vec2(", ", ", ")"); break; + case EOpConstructVec3: writeTriplet(visit, "vec3(", ", ", ")"); break; + case EOpConstructVec4: writeTriplet(visit, "vec4(", ", ", ")"); break; + case EOpConstructBool: writeTriplet(visit, "bool(", NULL, ")"); break; + case EOpConstructBVec2: writeTriplet(visit, "bvec2(", ", ", ")"); break; + case EOpConstructBVec3: writeTriplet(visit, "bvec3(", ", ", ")"); break; + case EOpConstructBVec4: writeTriplet(visit, "bvec4(", ", ", ")"); break; + case EOpConstructInt: writeTriplet(visit, "int(", NULL, ")"); break; + case EOpConstructIVec2: writeTriplet(visit, "ivec2(", ", ", ")"); break; + case EOpConstructIVec3: writeTriplet(visit, "ivec3(", ", ", ")"); break; + case EOpConstructIVec4: writeTriplet(visit, "ivec4(", ", ", ")"); break; + case EOpConstructMat2: writeTriplet(visit, "mat2(", ", ", ")"); break; + case EOpConstructMat3: writeTriplet(visit, "mat3(", ", ", ")"); break; + case EOpConstructMat4: writeTriplet(visit, "mat4(", ", ", ")"); break; + case EOpConstructStruct: + if (visit == PreVisit) + { + const TType& type = node->getType(); + ASSERT(type.getBasicType() == EbtStruct); + out << hashName(type.getStruct()->name()) << "("; + } + else if (visit == InVisit) + { + out << ", "; + } + else + { + out << ")"; + } + break; + + case EOpLessThan: preString = "lessThan("; delayedWrite = true; break; + case EOpGreaterThan: preString = "greaterThan("; delayedWrite = true; break; + case EOpLessThanEqual: preString = "lessThanEqual("; delayedWrite = true; break; + case EOpGreaterThanEqual: preString = "greaterThanEqual("; delayedWrite = true; break; + case EOpVectorEqual: preString = "equal("; delayedWrite = true; break; + case EOpVectorNotEqual: preString = "notEqual("; delayedWrite = true; break; + case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break; + + case EOpMod: preString = "mod("; delayedWrite = true; break; + case EOpPow: preString = "pow("; delayedWrite = true; break; + case EOpAtan: preString = "atan("; delayedWrite = true; break; + case EOpMin: preString = "min("; delayedWrite = true; break; + case EOpMax: preString = "max("; delayedWrite = true; break; + case EOpClamp: preString = "clamp("; delayedWrite = true; break; + case EOpMix: preString = "mix("; delayedWrite = true; break; + case EOpStep: preString = "step("; delayedWrite = true; break; + case EOpSmoothStep: preString = "smoothstep("; delayedWrite = true; break; + + case EOpDistance: preString = "distance("; delayedWrite = true; break; + case EOpDot: preString = "dot("; delayedWrite = true; break; + case EOpCross: preString = "cross("; delayedWrite = true; break; + case EOpFaceForward: preString = "faceforward("; delayedWrite = true; break; + case EOpReflect: preString = "reflect("; delayedWrite = true; break; + case EOpRefract: preString = "refract("; delayedWrite = true; break; + case EOpMul: preString = "matrixCompMult("; delayedWrite = true; break; + + default: UNREACHABLE(); break; + } + if (delayedWrite && visit == PreVisit && node->getUseEmulatedFunction()) + preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString); + if (delayedWrite) + writeTriplet(visit, preString.c_str(), ", ", ")"); + return visitChildren; +} + +bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node) +{ + TInfoSinkBase& out = objSink(); + + incrementDepth(node); + // Loop header. + TLoopType loopType = node->getType(); + if (loopType == ELoopFor) // for loop + { + if (!node->getUnrollFlag()) { + out << "for ("; + if (node->getInit()) + node->getInit()->traverse(this); + out << "; "; + + if (node->getCondition()) + node->getCondition()->traverse(this); + out << "; "; + + if (node->getExpression()) + node->getExpression()->traverse(this); + out << ")\n"; + } + } + else if (loopType == ELoopWhile) // while loop + { + out << "while ("; + ASSERT(node->getCondition() != NULL); + node->getCondition()->traverse(this); + out << ")\n"; + } + else // do-while loop + { + ASSERT(loopType == ELoopDoWhile); + out << "do\n"; + } + + // Loop body. + if (node->getUnrollFlag()) + { + TLoopIndexInfo indexInfo; + mLoopUnroll.FillLoopIndexInfo(node, indexInfo); + mLoopUnroll.Push(indexInfo); + while (mLoopUnroll.SatisfiesLoopCondition()) + { + visitCodeBlock(node->getBody()); + mLoopUnroll.Step(); + } + mLoopUnroll.Pop(); + } + else + { + visitCodeBlock(node->getBody()); + } + + // Loop footer. + if (loopType == ELoopDoWhile) // do-while loop + { + out << "while ("; + ASSERT(node->getCondition() != NULL); + node->getCondition()->traverse(this); + out << ");\n"; + } + decrementDepth(); + + // No need to visit children. They have been already processed in + // this function. + return false; +} + +bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch* node) +{ + switch (node->getFlowOp()) + { + case EOpKill: writeTriplet(visit, "discard", NULL, NULL); break; + case EOpBreak: writeTriplet(visit, "break", NULL, NULL); break; + case EOpContinue: writeTriplet(visit, "continue", NULL, NULL); break; + case EOpReturn: writeTriplet(visit, "return ", NULL, NULL); break; + default: UNREACHABLE(); break; + } + + return true; +} + +void TOutputGLSLBase::visitCodeBlock(TIntermNode* node) { + TInfoSinkBase &out = objSink(); + if (node != NULL) + { + node->traverse(this); + // Single statements not part of a sequence need to be terminated + // with semi-colon. + if (isSingleStatement(node)) + out << ";\n"; + } + else + { + out << "{\n}\n"; // Empty code block. + } +} + +TString TOutputGLSLBase::getTypeName(const TType& type) +{ + TInfoSinkBase out; + if (type.isMatrix()) + { + out << "mat"; + out << type.getNominalSize(); + } + else if (type.isVector()) + { + switch (type.getBasicType()) + { + case EbtFloat: out << "vec"; break; + case EbtInt: out << "ivec"; break; + case EbtBool: out << "bvec"; break; + default: UNREACHABLE(); break; + } + out << type.getNominalSize(); + } + else + { + if (type.getBasicType() == EbtStruct) + out << hashName(type.getStruct()->name()); + else + out << type.getBasicString(); + } + return TString(out.c_str()); +} + +TString TOutputGLSLBase::hashName(const TString& name) +{ + if (mHashFunction == NULL || name.empty()) + return name; + NameMap::const_iterator it = mNameMap.find(name.c_str()); + if (it != mNameMap.end()) + return it->second.c_str(); + TString hashedName = TIntermTraverser::hash(name, mHashFunction); + mNameMap[name.c_str()] = hashedName.c_str(); + return hashedName; +} + +TString TOutputGLSLBase::hashVariableName(const TString& name) +{ + if (mSymbolTable.findBuiltIn(name) != NULL) + return name; + return hashName(name); +} + +TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name) +{ + TString name = TFunction::unmangleName(mangled_name); + if (mSymbolTable.findBuiltIn(mangled_name) != NULL || name == "main") + return name; + return hashName(name); +} + +bool TOutputGLSLBase::structDeclared(const TStructure* structure) const +{ + return mDeclaredStructs.find(structure->name()) != mDeclaredStructs.end(); +} + +void TOutputGLSLBase::declareStruct(const TStructure* structure) +{ + TInfoSinkBase& out = objSink(); + + out << "struct " << hashName(structure->name()) << "{\n"; + const TFieldList& fields = structure->fields(); + for (size_t i = 0; i < fields.size(); ++i) + { + const TField* field = fields[i]; + if (writeVariablePrecision(field->type()->getPrecision())) + out << " "; + out << getTypeName(*field->type()) << " " << hashName(field->name()); + if (field->type()->isArray()) + out << arrayBrackets(*field->type()); + out << ";\n"; + } + out << "}"; + + mDeclaredStructs.insert(structure->name()); +} diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h new file mode 100644 index 0000000000..76bec4de61 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h @@ -0,0 +1,79 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ +#define CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ + +#include + +#include "compiler/translator/ForLoopUnroll.h" +#include "compiler/translator/intermediate.h" +#include "compiler/translator/ParseContext.h" + +class TOutputGLSLBase : public TIntermTraverser +{ +public: + TOutputGLSLBase(TInfoSinkBase& objSink, + ShArrayIndexClampingStrategy clampingStrategy, + ShHashFunction64 hashFunction, + NameMap& nameMap, + TSymbolTable& symbolTable); + +protected: + TInfoSinkBase& objSink() { return mObjSink; } + void writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr); + void writeVariableType(const TType& type); + virtual bool writeVariablePrecision(TPrecision precision) = 0; + void writeFunctionParameters(const TIntermSequence& args); + const ConstantUnion* writeConstantUnion(const TType& type, const ConstantUnion* pConstUnion); + TString getTypeName(const TType& type); + + virtual void visitSymbol(TIntermSymbol* node); + virtual void visitConstantUnion(TIntermConstantUnion* node); + virtual bool visitBinary(Visit visit, TIntermBinary* node); + virtual bool visitUnary(Visit visit, TIntermUnary* node); + virtual bool visitSelection(Visit visit, TIntermSelection* node); + virtual bool visitAggregate(Visit visit, TIntermAggregate* node); + virtual bool visitLoop(Visit visit, TIntermLoop* node); + virtual bool visitBranch(Visit visit, TIntermBranch* node); + + void visitCodeBlock(TIntermNode* node); + + + // Return the original name if hash function pointer is NULL; + // otherwise return the hashed name. + TString hashName(const TString& name); + // Same as hashName(), but without hashing built-in variables. + TString hashVariableName(const TString& name); + // Same as hashName(), but without hashing built-in functions. + TString hashFunctionName(const TString& mangled_name); + +private: + bool structDeclared(const TStructure* structure) const; + void declareStruct(const TStructure* structure); + + TInfoSinkBase& mObjSink; + bool mDeclaringVariables; + + // Structs are declared as the tree is traversed. This set contains all + // the structs already declared. It is maintained so that a struct is + // declared only once. + typedef std::set DeclaredStructs; + DeclaredStructs mDeclaredStructs; + + ForLoopUnroll mLoopUnroll; + + ShArrayIndexClampingStrategy mClampingStrategy; + + // name hashing. + ShHashFunction64 mHashFunction; + + NameMap& mNameMap; + + TSymbolTable& mSymbolTable; +}; + +#endif // CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp new file mode 100644 index 0000000000..af996df719 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp @@ -0,0 +1,3138 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/OutputHLSL.h" + +#include "common/angleutils.h" +#include "compiler/translator/compilerdebug.h" +#include "compiler/translator/DetectDiscontinuity.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/SearchSymbol.h" +#include "compiler/translator/UnfoldShortCircuit.h" +#include "compiler/translator/NodeSearch.h" +#include "compiler/translator/RewriteElseBlocks.h" + +#include +#include +#include + +namespace sh +{ + +OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType) + : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType) +{ + mUnfoldShortCircuit = new UnfoldShortCircuit(context, this); + mInsideFunction = false; + + mUsesTexture2D = false; + mUsesTexture2D_bias = false; + mUsesTexture2DProj = false; + mUsesTexture2DProj_bias = false; + mUsesTexture2DProjLod = false; + mUsesTexture2DLod = false; + mUsesTextureCube = false; + mUsesTextureCube_bias = false; + mUsesTextureCubeLod = false; + mUsesTexture2DLod0 = false; + mUsesTexture2DLod0_bias = false; + mUsesTexture2DProjLod0 = false; + mUsesTexture2DProjLod0_bias = false; + mUsesTextureCubeLod0 = false; + mUsesTextureCubeLod0_bias = false; + mUsesFragColor = false; + mUsesFragData = false; + mUsesDepthRange = false; + mUsesFragCoord = false; + mUsesPointCoord = false; + mUsesFrontFacing = false; + mUsesPointSize = false; + mUsesFragDepth = false; + mUsesXor = false; + mUsesMod1 = false; + mUsesMod2v = false; + mUsesMod2f = false; + mUsesMod3v = false; + mUsesMod3f = false; + mUsesMod4v = false; + mUsesMod4f = false; + mUsesFaceforward1 = false; + mUsesFaceforward2 = false; + mUsesFaceforward3 = false; + mUsesFaceforward4 = false; + mUsesAtan2_1 = false; + mUsesAtan2_2 = false; + mUsesAtan2_3 = false; + mUsesAtan2_4 = false; + mUsesDiscardRewriting = false; + + mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; + + mScopeDepth = 0; + + mUniqueIndex = 0; + + mContainsLoopDiscontinuity = false; + mOutputLod0Function = false; + mInsideDiscontinuousLoop = false; + + mExcessiveLoopIndex = NULL; + + if (mOutputType == SH_HLSL9_OUTPUT) + { + if (mContext.shaderType == SH_FRAGMENT_SHADER) + { + mUniformRegister = 3; // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront + } + else + { + mUniformRegister = 2; // Reserve registers for dx_DepthRange and dx_ViewAdjust + } + } + else + { + mUniformRegister = 0; + } + + mSamplerRegister = 0; +} + +OutputHLSL::~OutputHLSL() +{ + delete mUnfoldShortCircuit; +} + +void OutputHLSL::output() +{ + mContainsLoopDiscontinuity = mContext.shaderType == SH_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot); + + // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which + // use a vertex attribute as a condition, and some related computation in the else block. + if (mOutputType == SH_HLSL9_OUTPUT && mContext.shaderType == SH_VERTEX_SHADER) + { + RewriteElseBlocks(mContext.treeRoot); + } + + mContext.treeRoot->traverse(this); // Output the body first to determine what has to go in the header + header(); + + mContext.infoSink().obj << mHeader.c_str(); + mContext.infoSink().obj << mBody.c_str(); +} + +TInfoSinkBase &OutputHLSL::getBodyStream() +{ + return mBody; +} + +const ActiveUniforms &OutputHLSL::getUniforms() +{ + return mActiveUniforms; +} + +int OutputHLSL::vectorSize(const TType &type) const +{ + int elementSize = type.isMatrix() ? type.getNominalSize() : 1; + int arraySize = type.isArray() ? type.getArraySize() : 1; + + return elementSize * arraySize; +} + +void OutputHLSL::header() +{ + ShShaderType shaderType = mContext.shaderType; + TInfoSinkBase &out = mHeader; + + for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++) + { + out << *structDeclaration; + } + + for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++) + { + out << *constructor; + } + + TString uniforms; + TString varyings; + TString attributes; + + for (ReferencedSymbols::const_iterator uniform = mReferencedUniforms.begin(); uniform != mReferencedUniforms.end(); uniform++) + { + const TType &type = uniform->second->getType(); + const TString &name = uniform->second->getSymbol(); + + if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) // Also declare the texture + { + int index = samplerRegister(mReferencedUniforms[name]); + + uniforms += "uniform SamplerState sampler_" + decorateUniform(name, type) + arrayString(type) + + " : register(s" + str(index) + ");\n"; + + uniforms += "uniform " + textureString(type) + " texture_" + decorateUniform(name, type) + arrayString(type) + + " : register(t" + str(index) + ");\n"; + } + else + { + uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) + + " : register(" + registerString(mReferencedUniforms[name]) + ");\n"; + } + } + + for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); varying != mReferencedVaryings.end(); varying++) + { + const TType &type = varying->second->getType(); + const TString &name = varying->second->getSymbol(); + + // Program linking depends on this exact format + varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; + } + + for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); attribute != mReferencedAttributes.end(); attribute++) + { + const TType &type = attribute->second->getType(); + const TString &name = attribute->second->getSymbol(); + + attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; + } + + if (mUsesDiscardRewriting) + { + out << "#define ANGLE_USES_DISCARD_REWRITING" << "\n"; + } + + if (shaderType == SH_FRAGMENT_SHADER) + { + TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers"); + const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire)); + + const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1; + + out << "// Varyings\n"; + out << varyings; + out << "\n" + "static float4 gl_Color[" << numColorValues << "] =\n" + "{\n"; + for (unsigned int i = 0; i < numColorValues; i++) + { + out << " float4(0, 0, 0, 0)"; + if (i + 1 != numColorValues) + { + out << ","; + } + out << "\n"; + } + out << "};\n"; + + if (mUsesFragDepth) + { + out << "static float gl_Depth = 0.0;\n"; + } + + if (mUsesFragCoord) + { + out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n"; + } + + if (mUsesPointCoord) + { + out << "static float2 gl_PointCoord = float2(0.5, 0.5);\n"; + } + + if (mUsesFrontFacing) + { + out << "static bool gl_FrontFacing = false;\n"; + } + + out << "\n"; + + if (mUsesDepthRange) + { + out << "struct gl_DepthRangeParameters\n" + "{\n" + " float near;\n" + " float far;\n" + " float diff;\n" + "};\n" + "\n"; + } + + if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "cbuffer DriverConstants : register(b1)\n" + "{\n"; + + if (mUsesDepthRange) + { + out << " float3 dx_DepthRange : packoffset(c0);\n"; + } + + if (mUsesFragCoord) + { + out << " float4 dx_ViewCoords : packoffset(c1);\n"; + } + + if (mUsesFragCoord || mUsesFrontFacing) + { + out << " float3 dx_DepthFront : packoffset(c2);\n"; + } + + out << "};\n"; + } + else + { + if (mUsesDepthRange) + { + out << "uniform float3 dx_DepthRange : register(c0);"; + } + + if (mUsesFragCoord) + { + out << "uniform float4 dx_ViewCoords : register(c1);\n"; + } + + if (mUsesFragCoord || mUsesFrontFacing) + { + out << "uniform float3 dx_DepthFront : register(c2);\n"; + } + } + + out << "\n"; + + if (mUsesDepthRange) + { + out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" + "\n"; + } + + out << uniforms; + out << "\n"; + + if (mUsesTexture2D) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2D(sampler2D s, float2 t)\n" + "{\n" + " return tex2D(s, t);\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n" + "{\n" + " return t.Sample(s, uv);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + if (mUsesTexture2D_bias) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n" + "{\n" + " return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv, float bias)\n" + "{\n" + " return t.SampleBias(s, uv, bias);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + if (mUsesTexture2DProj) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n" + "{\n" + " return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n" + "}\n" + "\n" + "float4 gl_texture2DProj(sampler2D s, float4 t)\n" + "{\n" + " return tex2Dproj(s, t);\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n" + "{\n" + " return t.Sample(s, float2(uvw.x / uvw.z, uvw.y / uvw.z));\n" + "}\n" + "\n" + "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n" + "{\n" + " return t.Sample(s, float2(uvw.x / uvw.w, uvw.y / uvw.w));\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + if (mUsesTexture2DProj_bias) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DProj(sampler2D s, float3 t, float bias)\n" + "{\n" + " return tex2Dbias(s, float4(t.x / t.z, t.y / t.z, 0, bias));\n" + "}\n" + "\n" + "float4 gl_texture2DProj(sampler2D s, float4 t, float bias)\n" + "{\n" + " return tex2Dbias(s, float4(t.x / t.w, t.y / t.w, 0, bias));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw, float bias)\n" + "{\n" + " return t.SampleBias(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), bias);\n" + "}\n" + "\n" + "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw, float bias)\n" + "{\n" + " return t.SampleBias(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), bias);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + if (mUsesTextureCube) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" + "{\n" + " return texCUBE(s, t);\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n" + "{\n" + " return t.Sample(s, uvw);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + if (mUsesTextureCube_bias) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_textureCube(samplerCUBE s, float3 t, float bias)\n" + "{\n" + " return texCUBEbias(s, float4(t.x, t.y, t.z, bias));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw, float bias)\n" + "{\n" + " return t.SampleBias(s, uvw, bias);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + // These *Lod0 intrinsics are not available in GL fragment shaders. + // They are used to sample using discontinuous texture coordinates. + if (mUsesTexture2DLod0) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DLod0(sampler2D s, float2 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv)\n" + "{\n" + " return t.SampleLevel(s, uv, 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + if (mUsesTexture2DLod0_bias) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DLod0(sampler2D s, float2 t, float bias)\n" + "{\n" + " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv, float bias)\n" + "{\n" + " return t.SampleLevel(s, uv, 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + if (mUsesTexture2DProjLod0) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DProjLod0(sampler2D s, float3 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" + "}\n" + "\n" + "float4 gl_texture2DProjLod(sampler2D s, float4 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float3 uvw)\n" + "{\n" + " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n" + "}\n" + "\n" + "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float4 uvw)\n" + "{\n" + " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + if (mUsesTexture2DProjLod0_bias) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DProjLod0_bias(sampler2D s, float3 t, float bias)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" + "}\n" + "\n" + "float4 gl_texture2DProjLod_bias(sampler2D s, float4 t, float bias)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float3 uvw, float bias)\n" + "{\n" + " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n" + "}\n" + "\n" + "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float4 uvw, float bias)\n" + "{\n" + " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + if (mUsesTextureCubeLod0) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t)\n" + "{\n" + " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw)\n" + "{\n" + " return t.SampleLevel(s, uvw, 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + if (mUsesTextureCubeLod0_bias) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t, float bias)\n" + "{\n" + " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw, float bias)\n" + "{\n" + " return t.SampleLevel(s, uvw, 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + if (usingMRTExtension && mNumRenderTargets > 1) + { + out << "#define GL_USES_MRT\n"; + } + + if (mUsesFragColor) + { + out << "#define GL_USES_FRAG_COLOR\n"; + } + + if (mUsesFragData) + { + out << "#define GL_USES_FRAG_DATA\n"; + } + } + else // Vertex shader + { + out << "// Attributes\n"; + out << attributes; + out << "\n" + "static float4 gl_Position = float4(0, 0, 0, 0);\n"; + + if (mUsesPointSize) + { + out << "static float gl_PointSize = float(1);\n"; + } + + out << "\n" + "// Varyings\n"; + out << varyings; + out << "\n"; + + if (mUsesDepthRange) + { + out << "struct gl_DepthRangeParameters\n" + "{\n" + " float near;\n" + " float far;\n" + " float diff;\n" + "};\n" + "\n"; + } + + if (mOutputType == SH_HLSL11_OUTPUT) + { + if (mUsesDepthRange) + { + out << "cbuffer DriverConstants : register(b1)\n" + "{\n" + " float3 dx_DepthRange : packoffset(c0);\n" + "};\n" + "\n"; + } + } + else + { + if (mUsesDepthRange) + { + out << "uniform float3 dx_DepthRange : register(c0);\n"; + } + + out << "uniform float4 dx_ViewAdjust : register(c1);\n" + "\n"; + } + + if (mUsesDepthRange) + { + out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" + "\n"; + } + + out << uniforms; + out << "\n"; + + if (mUsesTexture2D) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2D(sampler2D s, float2 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n" + "{\n" + " return t.SampleLevel(s, uv, 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + if (mUsesTexture2DLod) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DLod(sampler2D s, float2 t, float lod)\n" + "{\n" + " return tex2Dlod(s, float4(t.x, t.y, 0, lod));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DLod(Texture2D t, SamplerState s, float2 uv, float lod)\n" + "{\n" + " return t.SampleLevel(s, uv, lod);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + if (mUsesTexture2DProj) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" + "}\n" + "\n" + "float4 gl_texture2DProj(sampler2D s, float4 t)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n" + "{\n" + " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n" + "}\n" + "\n" + "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n" + "{\n" + " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + if (mUsesTexture2DProjLod) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_texture2DProjLod(sampler2D s, float3 t, float lod)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, lod));\n" + "}\n" + "\n" + "float4 gl_texture2DProjLod(sampler2D s, float4 t, float lod)\n" + "{\n" + " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, lod));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_texture2DProjLod(Texture2D t, SamplerState s, float3 uvw, float lod)\n" + "{\n" + " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), lod);\n" + "}\n" + "\n" + "float4 gl_texture2DProjLod(Texture2D t, SamplerState s, float4 uvw, float lod)\n" + "{\n" + " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), lod);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + if (mUsesTextureCube) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" + "{\n" + " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n" + "{\n" + " return t.SampleLevel(s, uvw, 0);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + + if (mUsesTextureCubeLod) + { + if (mOutputType == SH_HLSL9_OUTPUT) + { + out << "float4 gl_textureCubeLod(samplerCUBE s, float3 t, float lod)\n" + "{\n" + " return texCUBElod(s, float4(t.x, t.y, t.z, lod));\n" + "}\n" + "\n"; + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + out << "float4 gl_textureCubeLod(TextureCube t, SamplerState s, float3 uvw, float lod)\n" + "{\n" + " return t.SampleLevel(s, uvw, lod);\n" + "}\n" + "\n"; + } + else UNREACHABLE(); + } + } + + if (mUsesFragCoord) + { + out << "#define GL_USES_FRAG_COORD\n"; + } + + if (mUsesPointCoord) + { + out << "#define GL_USES_POINT_COORD\n"; + } + + if (mUsesFrontFacing) + { + out << "#define GL_USES_FRONT_FACING\n"; + } + + if (mUsesPointSize) + { + out << "#define GL_USES_POINT_SIZE\n"; + } + + if (mUsesFragDepth) + { + out << "#define GL_USES_FRAG_DEPTH\n"; + } + + if (mUsesDepthRange) + { + out << "#define GL_USES_DEPTH_RANGE\n"; + } + + if (mUsesXor) + { + out << "bool xor(bool p, bool q)\n" + "{\n" + " return (p || q) && !(p && q);\n" + "}\n" + "\n"; + } + + if (mUsesMod1) + { + out << "float mod(float x, float y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"; + } + + if (mUsesMod2v) + { + out << "float2 mod(float2 x, float2 y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"; + } + + if (mUsesMod2f) + { + out << "float2 mod(float2 x, float y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"; + } + + if (mUsesMod3v) + { + out << "float3 mod(float3 x, float3 y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"; + } + + if (mUsesMod3f) + { + out << "float3 mod(float3 x, float y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"; + } + + if (mUsesMod4v) + { + out << "float4 mod(float4 x, float4 y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"; + } + + if (mUsesMod4f) + { + out << "float4 mod(float4 x, float y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"; + } + + if (mUsesFaceforward1) + { + out << "float faceforward(float N, float I, float Nref)\n" + "{\n" + " if(dot(Nref, I) >= 0)\n" + " {\n" + " return -N;\n" + " }\n" + " else\n" + " {\n" + " return N;\n" + " }\n" + "}\n" + "\n"; + } + + if (mUsesFaceforward2) + { + out << "float2 faceforward(float2 N, float2 I, float2 Nref)\n" + "{\n" + " if(dot(Nref, I) >= 0)\n" + " {\n" + " return -N;\n" + " }\n" + " else\n" + " {\n" + " return N;\n" + " }\n" + "}\n" + "\n"; + } + + if (mUsesFaceforward3) + { + out << "float3 faceforward(float3 N, float3 I, float3 Nref)\n" + "{\n" + " if(dot(Nref, I) >= 0)\n" + " {\n" + " return -N;\n" + " }\n" + " else\n" + " {\n" + " return N;\n" + " }\n" + "}\n" + "\n"; + } + + if (mUsesFaceforward4) + { + out << "float4 faceforward(float4 N, float4 I, float4 Nref)\n" + "{\n" + " if(dot(Nref, I) >= 0)\n" + " {\n" + " return -N;\n" + " }\n" + " else\n" + " {\n" + " return N;\n" + " }\n" + "}\n" + "\n"; + } + + if (mUsesAtan2_1) + { + out << "float atanyx(float y, float x)\n" + "{\n" + " if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN + " return atan2(y, x);\n" + "}\n"; + } + + if (mUsesAtan2_2) + { + out << "float2 atanyx(float2 y, float2 x)\n" + "{\n" + " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" + " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" + " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n" + "}\n"; + } + + if (mUsesAtan2_3) + { + out << "float3 atanyx(float3 y, float3 x)\n" + "{\n" + " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" + " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" + " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" + " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n" + "}\n"; + } + + if (mUsesAtan2_4) + { + out << "float4 atanyx(float4 y, float4 x)\n" + "{\n" + " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" + " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" + " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" + " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n" + " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n" + "}\n"; + } +} + +void OutputHLSL::visitSymbol(TIntermSymbol *node) +{ + TInfoSinkBase &out = mBody; + + TString name = node->getSymbol(); + + if (name == "gl_FragColor") + { + out << "gl_Color[0]"; + mUsesFragColor = true; + } + else if (name == "gl_FragData") + { + out << "gl_Color"; + mUsesFragData = true; + } + else if (name == "gl_DepthRange") + { + mUsesDepthRange = true; + out << name; + } + else if (name == "gl_FragCoord") + { + mUsesFragCoord = true; + out << name; + } + else if (name == "gl_PointCoord") + { + mUsesPointCoord = true; + out << name; + } + else if (name == "gl_FrontFacing") + { + mUsesFrontFacing = true; + out << name; + } + else if (name == "gl_PointSize") + { + mUsesPointSize = true; + out << name; + } + else if (name == "gl_FragDepthEXT") + { + mUsesFragDepth = true; + out << "gl_Depth"; + } + else + { + TQualifier qualifier = node->getQualifier(); + + if (qualifier == EvqUniform) + { + mReferencedUniforms[name] = node; + out << decorateUniform(name, node->getType()); + } + else if (qualifier == EvqAttribute) + { + mReferencedAttributes[name] = node; + out << decorate(name); + } + else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut || qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn) + { + mReferencedVaryings[name] = node; + out << decorate(name); + } + else if (qualifier == EvqInternal) + { + out << name; + } + else + { + out << decorate(name); + } + } +} + +bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) +{ + TInfoSinkBase &out = mBody; + + switch (node->getOp()) + { + case EOpAssign: outputTriplet(visit, "(", " = ", ")"); break; + case EOpInitialize: + if (visit == PreVisit) + { + // GLSL allows to write things like "float x = x;" where a new variable x is defined + // and the value of an existing variable x is assigned. HLSL uses C semantics (the + // new variable is created before the assignment is evaluated), so we need to convert + // this to "float t = x, x = t;". + + TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode(); + TIntermTyped *expression = node->getRight(); + + sh::SearchSymbol searchSymbol(symbolNode->getSymbol()); + expression->traverse(&searchSymbol); + bool sameSymbol = searchSymbol.foundMatch(); + + if (sameSymbol) + { + // Type already printed + out << "t" + str(mUniqueIndex) + " = "; + expression->traverse(this); + out << ", "; + symbolNode->traverse(this); + out << " = t" + str(mUniqueIndex); + + mUniqueIndex++; + return false; + } + } + else if (visit == InVisit) + { + out << " = "; + } + break; + case EOpAddAssign: outputTriplet(visit, "(", " += ", ")"); break; + case EOpSubAssign: outputTriplet(visit, "(", " -= ", ")"); break; + case EOpMulAssign: outputTriplet(visit, "(", " *= ", ")"); break; + case EOpVectorTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break; + case EOpMatrixTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break; + case EOpVectorTimesMatrixAssign: + if (visit == PreVisit) + { + out << "("; + } + else if (visit == InVisit) + { + out << " = mul("; + node->getLeft()->traverse(this); + out << ", transpose("; + } + else + { + out << ")))"; + } + break; + case EOpMatrixTimesMatrixAssign: + if (visit == PreVisit) + { + out << "("; + } + else if (visit == InVisit) + { + out << " = mul("; + node->getLeft()->traverse(this); + out << ", "; + } + else + { + out << "))"; + } + break; + case EOpDivAssign: outputTriplet(visit, "(", " /= ", ")"); break; + case EOpIndexDirect: outputTriplet(visit, "", "[", "]"); break; + case EOpIndexIndirect: outputTriplet(visit, "", "[", "]"); break; + case EOpIndexDirectStruct: + if (visit == InVisit) + { + const TStructure* structure = node->getLeft()->getType().getStruct(); + const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion(); + const TField* field = structure->fields()[index->getIConst(0)]; + out << "." + decorateField(field->name(), node->getLeft()->getType()); + + return false; + } + break; + case EOpVectorSwizzle: + if (visit == InVisit) + { + out << "."; + + TIntermAggregate *swizzle = node->getRight()->getAsAggregate(); + + if (swizzle) + { + TIntermSequence &sequence = swizzle->getSequence(); + + for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) + { + TIntermConstantUnion *element = (*sit)->getAsConstantUnion(); + + if (element) + { + int i = element->getIConst(0); + + switch (i) + { + case 0: out << "x"; break; + case 1: out << "y"; break; + case 2: out << "z"; break; + case 3: out << "w"; break; + default: UNREACHABLE(); + } + } + else UNREACHABLE(); + } + } + else UNREACHABLE(); + + return false; // Fully processed + } + break; + case EOpAdd: outputTriplet(visit, "(", " + ", ")"); break; + case EOpSub: outputTriplet(visit, "(", " - ", ")"); break; + case EOpMul: outputTriplet(visit, "(", " * ", ")"); break; + case EOpDiv: outputTriplet(visit, "(", " / ", ")"); break; + case EOpEqual: + case EOpNotEqual: + if (node->getLeft()->isScalar()) + { + if (node->getOp() == EOpEqual) + { + outputTriplet(visit, "(", " == ", ")"); + } + else + { + outputTriplet(visit, "(", " != ", ")"); + } + } + else if (node->getLeft()->getBasicType() == EbtStruct) + { + if (node->getOp() == EOpEqual) + { + out << "("; + } + else + { + out << "!("; + } + + const TFieldList &fields = node->getLeft()->getType().getStruct()->fields(); + + for (size_t i = 0; i < fields.size(); i++) + { + const TField *field = fields[i]; + + node->getLeft()->traverse(this); + out << "." + decorateField(field->name(), node->getLeft()->getType()) + " == "; + node->getRight()->traverse(this); + out << "." + decorateField(field->name(), node->getLeft()->getType()); + + if (i < fields.size() - 1) + { + out << " && "; + } + } + + out << ")"; + + return false; + } + else + { + ASSERT(node->getLeft()->isMatrix() || node->getLeft()->isVector()); + + if (node->getOp() == EOpEqual) + { + outputTriplet(visit, "all(", " == ", ")"); + } + else + { + outputTriplet(visit, "!all(", " == ", ")"); + } + } + break; + case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; + case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break; + case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break; + case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break; + case EOpVectorTimesScalar: outputTriplet(visit, "(", " * ", ")"); break; + case EOpMatrixTimesScalar: outputTriplet(visit, "(", " * ", ")"); break; + case EOpVectorTimesMatrix: outputTriplet(visit, "mul(", ", transpose(", "))"); break; + case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break; + case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break; + case EOpLogicalOr: + if (node->getRight()->hasSideEffects()) + { + out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex(); + return false; + } + else + { + outputTriplet(visit, "(", " || ", ")"); + return true; + } + case EOpLogicalXor: + mUsesXor = true; + outputTriplet(visit, "xor(", ", ", ")"); + break; + case EOpLogicalAnd: + if (node->getRight()->hasSideEffects()) + { + out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex(); + return false; + } + else + { + outputTriplet(visit, "(", " && ", ")"); + return true; + } + default: UNREACHABLE(); + } + + return true; +} + +bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) +{ + switch (node->getOp()) + { + case EOpNegative: outputTriplet(visit, "(-", "", ")"); break; + case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break; + case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break; + case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break; + case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break; + case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break; + case EOpPreDecrement: outputTriplet(visit, "(--", "", ")"); break; + case EOpConvIntToBool: + case EOpConvFloatToBool: + switch (node->getOperand()->getType().getNominalSize()) + { + case 1: outputTriplet(visit, "bool(", "", ")"); break; + case 2: outputTriplet(visit, "bool2(", "", ")"); break; + case 3: outputTriplet(visit, "bool3(", "", ")"); break; + case 4: outputTriplet(visit, "bool4(", "", ")"); break; + default: UNREACHABLE(); + } + break; + case EOpConvBoolToFloat: + case EOpConvIntToFloat: + switch (node->getOperand()->getType().getNominalSize()) + { + case 1: outputTriplet(visit, "float(", "", ")"); break; + case 2: outputTriplet(visit, "float2(", "", ")"); break; + case 3: outputTriplet(visit, "float3(", "", ")"); break; + case 4: outputTriplet(visit, "float4(", "", ")"); break; + default: UNREACHABLE(); + } + break; + case EOpConvFloatToInt: + case EOpConvBoolToInt: + switch (node->getOperand()->getType().getNominalSize()) + { + case 1: outputTriplet(visit, "int(", "", ")"); break; + case 2: outputTriplet(visit, "int2(", "", ")"); break; + case 3: outputTriplet(visit, "int3(", "", ")"); break; + case 4: outputTriplet(visit, "int4(", "", ")"); break; + default: UNREACHABLE(); + } + break; + case EOpRadians: outputTriplet(visit, "radians(", "", ")"); break; + case EOpDegrees: outputTriplet(visit, "degrees(", "", ")"); break; + case EOpSin: outputTriplet(visit, "sin(", "", ")"); break; + case EOpCos: outputTriplet(visit, "cos(", "", ")"); break; + case EOpTan: outputTriplet(visit, "tan(", "", ")"); break; + case EOpAsin: outputTriplet(visit, "asin(", "", ")"); break; + case EOpAcos: outputTriplet(visit, "acos(", "", ")"); break; + case EOpAtan: outputTriplet(visit, "atan(", "", ")"); break; + case EOpExp: outputTriplet(visit, "exp(", "", ")"); break; + case EOpLog: outputTriplet(visit, "log(", "", ")"); break; + case EOpExp2: outputTriplet(visit, "exp2(", "", ")"); break; + case EOpLog2: outputTriplet(visit, "log2(", "", ")"); break; + case EOpSqrt: outputTriplet(visit, "sqrt(", "", ")"); break; + case EOpInverseSqrt: outputTriplet(visit, "rsqrt(", "", ")"); break; + case EOpAbs: outputTriplet(visit, "abs(", "", ")"); break; + case EOpSign: outputTriplet(visit, "sign(", "", ")"); break; + case EOpFloor: outputTriplet(visit, "floor(", "", ")"); break; + case EOpCeil: outputTriplet(visit, "ceil(", "", ")"); break; + case EOpFract: outputTriplet(visit, "frac(", "", ")"); break; + case EOpLength: outputTriplet(visit, "length(", "", ")"); break; + case EOpNormalize: outputTriplet(visit, "normalize(", "", ")"); break; + case EOpDFdx: + if(mInsideDiscontinuousLoop || mOutputLod0Function) + { + outputTriplet(visit, "(", "", ", 0.0)"); + } + else + { + outputTriplet(visit, "ddx(", "", ")"); + } + break; + case EOpDFdy: + if(mInsideDiscontinuousLoop || mOutputLod0Function) + { + outputTriplet(visit, "(", "", ", 0.0)"); + } + else + { + outputTriplet(visit, "ddy(", "", ")"); + } + break; + case EOpFwidth: + if(mInsideDiscontinuousLoop || mOutputLod0Function) + { + outputTriplet(visit, "(", "", ", 0.0)"); + } + else + { + outputTriplet(visit, "fwidth(", "", ")"); + } + break; + case EOpAny: outputTriplet(visit, "any(", "", ")"); break; + case EOpAll: outputTriplet(visit, "all(", "", ")"); break; + default: UNREACHABLE(); + } + + return true; +} + +bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) +{ + TInfoSinkBase &out = mBody; + + switch (node->getOp()) + { + case EOpSequence: + { + if (mInsideFunction) + { + outputLineDirective(node->getLine().first_line); + out << "{\n"; + + mScopeDepth++; + + if (mScopeBracket.size() < mScopeDepth) + { + mScopeBracket.push_back(0); // New scope level + } + else + { + mScopeBracket[mScopeDepth - 1]++; // New scope at existing level + } + } + + for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++) + { + outputLineDirective((*sit)->getLine().first_line); + + traverseStatements(*sit); + + out << ";\n"; + } + + if (mInsideFunction) + { + outputLineDirective(node->getLine().last_line); + out << "}\n"; + + mScopeDepth--; + } + + return false; + } + case EOpDeclaration: + if (visit == PreVisit) + { + TIntermSequence &sequence = node->getSequence(); + TIntermTyped *variable = sequence[0]->getAsTyped(); + + if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal)) + { + if (variable->getType().getStruct()) + { + addConstructor(variable->getType(), scopedStruct(variable->getType().getStruct()->name()), NULL); + } + + if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration + { + if (!mInsideFunction) + { + out << "static "; + } + + out << typeString(variable->getType()) + " "; + + for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) + { + TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); + + if (symbol) + { + symbol->traverse(this); + out << arrayString(symbol->getType()); + out << " = " + initializer(symbol->getType()); + } + else + { + (*sit)->traverse(this); + } + + if (*sit != sequence.back()) + { + out << ", "; + } + } + } + else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration + { + // Already added to constructor map + } + else UNREACHABLE(); + } + else if (variable && (variable->getQualifier() == EvqVaryingOut || variable->getQualifier() == EvqInvariantVaryingOut)) + { + for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) + { + TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); + + if (symbol) + { + // Vertex (output) varyings which are declared but not written to should still be declared to allow successful linking + mReferencedVaryings[symbol->getSymbol()] = symbol; + } + else + { + (*sit)->traverse(this); + } + } + } + + return false; + } + else if (visit == InVisit) + { + out << ", "; + } + break; + case EOpPrototype: + if (visit == PreVisit) + { + out << typeString(node->getType()) << " " << decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "("); + + TIntermSequence &arguments = node->getSequence(); + + for (unsigned int i = 0; i < arguments.size(); i++) + { + TIntermSymbol *symbol = arguments[i]->getAsSymbolNode(); + + if (symbol) + { + out << argumentString(symbol); + + if (i < arguments.size() - 1) + { + out << ", "; + } + } + else UNREACHABLE(); + } + + out << ");\n"; + + // Also prototype the Lod0 variant if needed + if (mContainsLoopDiscontinuity && !mOutputLod0Function) + { + mOutputLod0Function = true; + node->traverse(this); + mOutputLod0Function = false; + } + + return false; + } + break; + case EOpComma: outputTriplet(visit, "(", ", ", ")"); break; + case EOpFunction: + { + TString name = TFunction::unmangleName(node->getName()); + + out << typeString(node->getType()) << " "; + + if (name == "main") + { + out << "gl_main("; + } + else + { + out << decorate(name) << (mOutputLod0Function ? "Lod0(" : "("); + } + + TIntermSequence &sequence = node->getSequence(); + TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence(); + + for (unsigned int i = 0; i < arguments.size(); i++) + { + TIntermSymbol *symbol = arguments[i]->getAsSymbolNode(); + + if (symbol) + { + if (symbol->getType().getStruct()) + { + addConstructor(symbol->getType(), scopedStruct(symbol->getType().getStruct()->name()), NULL); + } + + out << argumentString(symbol); + + if (i < arguments.size() - 1) + { + out << ", "; + } + } + else UNREACHABLE(); + } + + out << ")\n" + "{\n"; + + if (sequence.size() > 1) + { + mInsideFunction = true; + sequence[1]->traverse(this); + mInsideFunction = false; + } + + out << "}\n"; + + if (mContainsLoopDiscontinuity && !mOutputLod0Function) + { + if (name != "main") + { + mOutputLod0Function = true; + node->traverse(this); + mOutputLod0Function = false; + } + } + + return false; + } + break; + case EOpFunctionCall: + { + TString name = TFunction::unmangleName(node->getName()); + bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function; + + if (node->isUserDefined()) + { + out << decorate(name) << (lod0 ? "Lod0(" : "("); + } + else + { + if (name == "texture2D") + { + if (!lod0) + { + if (node->getSequence().size() == 2) + { + mUsesTexture2D = true; + } + else if (node->getSequence().size() == 3) + { + mUsesTexture2D_bias = true; + } + else UNREACHABLE(); + + out << "gl_texture2D("; + } + else + { + if (node->getSequence().size() == 2) + { + mUsesTexture2DLod0 = true; + } + else if (node->getSequence().size() == 3) + { + mUsesTexture2DLod0_bias = true; + } + else UNREACHABLE(); + + out << "gl_texture2DLod0("; + } + } + else if (name == "texture2DProj") + { + if (!lod0) + { + if (node->getSequence().size() == 2) + { + mUsesTexture2DProj = true; + } + else if (node->getSequence().size() == 3) + { + mUsesTexture2DProj_bias = true; + } + else UNREACHABLE(); + + out << "gl_texture2DProj("; + } + else + { + if (node->getSequence().size() == 2) + { + mUsesTexture2DProjLod0 = true; + } + else if (node->getSequence().size() == 3) + { + mUsesTexture2DProjLod0_bias = true; + } + else UNREACHABLE(); + + out << "gl_texture2DProjLod0("; + } + } + else if (name == "textureCube") + { + if (!lod0) + { + if (node->getSequence().size() == 2) + { + mUsesTextureCube = true; + } + else if (node->getSequence().size() == 3) + { + mUsesTextureCube_bias = true; + } + else UNREACHABLE(); + + out << "gl_textureCube("; + } + else + { + if (node->getSequence().size() == 2) + { + mUsesTextureCubeLod0 = true; + } + else if (node->getSequence().size() == 3) + { + mUsesTextureCubeLod0_bias = true; + } + else UNREACHABLE(); + + out << "gl_textureCubeLod0("; + } + } + else if (name == "texture2DLod") + { + if (node->getSequence().size() == 3) + { + mUsesTexture2DLod = true; + } + else UNREACHABLE(); + + out << "gl_texture2DLod("; + } + else if (name == "texture2DProjLod") + { + if (node->getSequence().size() == 3) + { + mUsesTexture2DProjLod = true; + } + else UNREACHABLE(); + + out << "gl_texture2DProjLod("; + } + else if (name == "textureCubeLod") + { + if (node->getSequence().size() == 3) + { + mUsesTextureCubeLod = true; + } + else UNREACHABLE(); + + out << "gl_textureCubeLod("; + } + else UNREACHABLE(); + } + + TIntermSequence &arguments = node->getSequence(); + + for (TIntermSequence::iterator arg = arguments.begin(); arg != arguments.end(); arg++) + { + if (mOutputType == SH_HLSL11_OUTPUT && IsSampler((*arg)->getAsTyped()->getBasicType())) + { + out << "texture_"; + (*arg)->traverse(this); + out << ", sampler_"; + } + + (*arg)->traverse(this); + + if (arg < arguments.end() - 1) + { + out << ", "; + } + } + + out << ")"; + + return false; + } + break; + case EOpParameters: outputTriplet(visit, "(", ", ", ")\n{\n"); break; + case EOpConstructFloat: + addConstructor(node->getType(), "vec1", &node->getSequence()); + outputTriplet(visit, "vec1(", "", ")"); + break; + case EOpConstructVec2: + addConstructor(node->getType(), "vec2", &node->getSequence()); + outputTriplet(visit, "vec2(", ", ", ")"); + break; + case EOpConstructVec3: + addConstructor(node->getType(), "vec3", &node->getSequence()); + outputTriplet(visit, "vec3(", ", ", ")"); + break; + case EOpConstructVec4: + addConstructor(node->getType(), "vec4", &node->getSequence()); + outputTriplet(visit, "vec4(", ", ", ")"); + break; + case EOpConstructBool: + addConstructor(node->getType(), "bvec1", &node->getSequence()); + outputTriplet(visit, "bvec1(", "", ")"); + break; + case EOpConstructBVec2: + addConstructor(node->getType(), "bvec2", &node->getSequence()); + outputTriplet(visit, "bvec2(", ", ", ")"); + break; + case EOpConstructBVec3: + addConstructor(node->getType(), "bvec3", &node->getSequence()); + outputTriplet(visit, "bvec3(", ", ", ")"); + break; + case EOpConstructBVec4: + addConstructor(node->getType(), "bvec4", &node->getSequence()); + outputTriplet(visit, "bvec4(", ", ", ")"); + break; + case EOpConstructInt: + addConstructor(node->getType(), "ivec1", &node->getSequence()); + outputTriplet(visit, "ivec1(", "", ")"); + break; + case EOpConstructIVec2: + addConstructor(node->getType(), "ivec2", &node->getSequence()); + outputTriplet(visit, "ivec2(", ", ", ")"); + break; + case EOpConstructIVec3: + addConstructor(node->getType(), "ivec3", &node->getSequence()); + outputTriplet(visit, "ivec3(", ", ", ")"); + break; + case EOpConstructIVec4: + addConstructor(node->getType(), "ivec4", &node->getSequence()); + outputTriplet(visit, "ivec4(", ", ", ")"); + break; + case EOpConstructMat2: + addConstructor(node->getType(), "mat2", &node->getSequence()); + outputTriplet(visit, "mat2(", ", ", ")"); + break; + case EOpConstructMat3: + addConstructor(node->getType(), "mat3", &node->getSequence()); + outputTriplet(visit, "mat3(", ", ", ")"); + break; + case EOpConstructMat4: + addConstructor(node->getType(), "mat4", &node->getSequence()); + outputTriplet(visit, "mat4(", ", ", ")"); + break; + case EOpConstructStruct: + addConstructor(node->getType(), scopedStruct(node->getType().getStruct()->name()), &node->getSequence()); + outputTriplet(visit, structLookup(node->getType().getStruct()->name()) + "_ctor(", ", ", ")"); + break; + case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; + case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break; + case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break; + case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break; + case EOpVectorEqual: outputTriplet(visit, "(", " == ", ")"); break; + case EOpVectorNotEqual: outputTriplet(visit, "(", " != ", ")"); break; + case EOpMod: + { + // We need to look at the number of components in both arguments + switch (node->getSequence()[0]->getAsTyped()->getNominalSize() * 10 + + node->getSequence()[1]->getAsTyped()->getNominalSize()) + { + case 11: mUsesMod1 = true; break; + case 22: mUsesMod2v = true; break; + case 21: mUsesMod2f = true; break; + case 33: mUsesMod3v = true; break; + case 31: mUsesMod3f = true; break; + case 44: mUsesMod4v = true; break; + case 41: mUsesMod4f = true; break; + default: UNREACHABLE(); + } + + outputTriplet(visit, "mod(", ", ", ")"); + } + break; + case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break; + case EOpAtan: + ASSERT(node->getSequence().size() == 2); // atan(x) is a unary operator + switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) + { + case 1: mUsesAtan2_1 = true; break; + case 2: mUsesAtan2_2 = true; break; + case 3: mUsesAtan2_3 = true; break; + case 4: mUsesAtan2_4 = true; break; + default: UNREACHABLE(); + } + outputTriplet(visit, "atanyx(", ", ", ")"); + break; + case EOpMin: outputTriplet(visit, "min(", ", ", ")"); break; + case EOpMax: outputTriplet(visit, "max(", ", ", ")"); break; + case EOpClamp: outputTriplet(visit, "clamp(", ", ", ")"); break; + case EOpMix: outputTriplet(visit, "lerp(", ", ", ")"); break; + case EOpStep: outputTriplet(visit, "step(", ", ", ")"); break; + case EOpSmoothStep: outputTriplet(visit, "smoothstep(", ", ", ")"); break; + case EOpDistance: outputTriplet(visit, "distance(", ", ", ")"); break; + case EOpDot: outputTriplet(visit, "dot(", ", ", ")"); break; + case EOpCross: outputTriplet(visit, "cross(", ", ", ")"); break; + case EOpFaceForward: + { + switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) // Number of components in the first argument + { + case 1: mUsesFaceforward1 = true; break; + case 2: mUsesFaceforward2 = true; break; + case 3: mUsesFaceforward3 = true; break; + case 4: mUsesFaceforward4 = true; break; + default: UNREACHABLE(); + } + + outputTriplet(visit, "faceforward(", ", ", ")"); + } + break; + case EOpReflect: outputTriplet(visit, "reflect(", ", ", ")"); break; + case EOpRefract: outputTriplet(visit, "refract(", ", ", ")"); break; + case EOpMul: outputTriplet(visit, "(", " * ", ")"); break; + default: UNREACHABLE(); + } + + return true; +} + +bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) +{ + TInfoSinkBase &out = mBody; + + if (node->usesTernaryOperator()) + { + out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex(); + } + else // if/else statement + { + mUnfoldShortCircuit->traverse(node->getCondition()); + + out << "if ("; + + node->getCondition()->traverse(this); + + out << ")\n"; + + outputLineDirective(node->getLine().first_line); + out << "{\n"; + + bool discard = false; + + if (node->getTrueBlock()) + { + traverseStatements(node->getTrueBlock()); + + // Detect true discard + discard = (discard || FindDiscard::search(node->getTrueBlock())); + } + + outputLineDirective(node->getLine().first_line); + out << ";\n}\n"; + + if (node->getFalseBlock()) + { + out << "else\n"; + + outputLineDirective(node->getFalseBlock()->getLine().first_line); + out << "{\n"; + + outputLineDirective(node->getFalseBlock()->getLine().first_line); + traverseStatements(node->getFalseBlock()); + + outputLineDirective(node->getFalseBlock()->getLine().first_line); + out << ";\n}\n"; + + // Detect false discard + discard = (discard || FindDiscard::search(node->getFalseBlock())); + } + + // ANGLE issue 486: Detect problematic conditional discard + if (discard && FindSideEffectRewriting::search(node)) + { + mUsesDiscardRewriting = true; + } + } + + return false; +} + +void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node) +{ + writeConstantUnion(node->getType(), node->getUnionArrayPointer()); +} + +bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) +{ + bool wasDiscontinuous = mInsideDiscontinuousLoop; + + if (mContainsLoopDiscontinuity && !mInsideDiscontinuousLoop) + { + mInsideDiscontinuousLoop = containsLoopDiscontinuity(node); + } + + if (mOutputType == SH_HLSL9_OUTPUT) + { + if (handleExcessiveLoop(node)) + { + return false; + } + } + + TInfoSinkBase &out = mBody; + + if (node->getType() == ELoopDoWhile) + { + out << "{do\n"; + + outputLineDirective(node->getLine().first_line); + out << "{\n"; + } + else + { + out << "{for("; + + if (node->getInit()) + { + node->getInit()->traverse(this); + } + + out << "; "; + + if (node->getCondition()) + { + node->getCondition()->traverse(this); + } + + out << "; "; + + if (node->getExpression()) + { + node->getExpression()->traverse(this); + } + + out << ")\n"; + + outputLineDirective(node->getLine().first_line); + out << "{\n"; + } + + if (node->getBody()) + { + traverseStatements(node->getBody()); + } + + outputLineDirective(node->getLine().first_line); + out << ";}\n"; + + if (node->getType() == ELoopDoWhile) + { + outputLineDirective(node->getCondition()->getLine().first_line); + out << "while(\n"; + + node->getCondition()->traverse(this); + + out << ");"; + } + + out << "}\n"; + + mInsideDiscontinuousLoop = wasDiscontinuous; + + return false; +} + +bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node) +{ + TInfoSinkBase &out = mBody; + + switch (node->getFlowOp()) + { + case EOpKill: + outputTriplet(visit, "discard;\n", "", ""); + break; + case EOpBreak: + if (visit == PreVisit) + { + if (mExcessiveLoopIndex) + { + out << "{Break"; + mExcessiveLoopIndex->traverse(this); + out << " = true; break;}\n"; + } + else + { + out << "break;\n"; + } + } + break; + case EOpContinue: outputTriplet(visit, "continue;\n", "", ""); break; + case EOpReturn: + if (visit == PreVisit) + { + if (node->getExpression()) + { + out << "return "; + } + else + { + out << "return;\n"; + } + } + else if (visit == PostVisit) + { + if (node->getExpression()) + { + out << ";\n"; + } + } + break; + default: UNREACHABLE(); + } + + return true; +} + +void OutputHLSL::traverseStatements(TIntermNode *node) +{ + if (isSingleStatement(node)) + { + mUnfoldShortCircuit->traverse(node); + } + + node->traverse(this); +} + +bool OutputHLSL::isSingleStatement(TIntermNode *node) +{ + TIntermAggregate *aggregate = node->getAsAggregate(); + + if (aggregate) + { + if (aggregate->getOp() == EOpSequence) + { + return false; + } + else + { + for (TIntermSequence::iterator sit = aggregate->getSequence().begin(); sit != aggregate->getSequence().end(); sit++) + { + if (!isSingleStatement(*sit)) + { + return false; + } + } + + return true; + } + } + + return true; +} + +// Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them +// (The D3D documentation says 255 iterations, but the compiler complains at anything more than 254). +bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) +{ + const int MAX_LOOP_ITERATIONS = 254; + TInfoSinkBase &out = mBody; + + // Parse loops of the form: + // for(int index = initial; index [comparator] limit; index += increment) + TIntermSymbol *index = NULL; + TOperator comparator = EOpNull; + int initial = 0; + int limit = 0; + int increment = 0; + + // Parse index name and intial value + if (node->getInit()) + { + TIntermAggregate *init = node->getInit()->getAsAggregate(); + + if (init) + { + TIntermSequence &sequence = init->getSequence(); + TIntermTyped *variable = sequence[0]->getAsTyped(); + + if (variable && variable->getQualifier() == EvqTemporary) + { + TIntermBinary *assign = variable->getAsBinaryNode(); + + if (assign->getOp() == EOpInitialize) + { + TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode(); + TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion(); + + if (symbol && constant) + { + if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) + { + index = symbol; + initial = constant->getIConst(0); + } + } + } + } + } + } + + // Parse comparator and limit value + if (index != NULL && node->getCondition()) + { + TIntermBinary *test = node->getCondition()->getAsBinaryNode(); + + if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId()) + { + TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion(); + + if (constant) + { + if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) + { + comparator = test->getOp(); + limit = constant->getIConst(0); + } + } + } + } + + // Parse increment + if (index != NULL && comparator != EOpNull && node->getExpression()) + { + TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode(); + TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode(); + + if (binaryTerminal) + { + TOperator op = binaryTerminal->getOp(); + TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion(); + + if (constant) + { + if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) + { + int value = constant->getIConst(0); + + switch (op) + { + case EOpAddAssign: increment = value; break; + case EOpSubAssign: increment = -value; break; + default: UNIMPLEMENTED(); + } + } + } + } + else if (unaryTerminal) + { + TOperator op = unaryTerminal->getOp(); + + switch (op) + { + case EOpPostIncrement: increment = 1; break; + case EOpPostDecrement: increment = -1; break; + case EOpPreIncrement: increment = 1; break; + case EOpPreDecrement: increment = -1; break; + default: UNIMPLEMENTED(); + } + } + } + + if (index != NULL && comparator != EOpNull && increment != 0) + { + if (comparator == EOpLessThanEqual) + { + comparator = EOpLessThan; + limit += 1; + } + + if (comparator == EOpLessThan) + { + int iterations = (limit - initial) / increment; + + if (iterations <= MAX_LOOP_ITERATIONS) + { + return false; // Not an excessive loop + } + + TIntermSymbol *restoreIndex = mExcessiveLoopIndex; + mExcessiveLoopIndex = index; + + out << "{int "; + index->traverse(this); + out << ";\n" + "bool Break"; + index->traverse(this); + out << " = false;\n"; + + bool firstLoopFragment = true; + + while (iterations > 0) + { + int clampedLimit = initial + increment * std::min(MAX_LOOP_ITERATIONS, iterations); + + if (!firstLoopFragment) + { + out << "if (!Break"; + index->traverse(this); + out << ") {\n"; + } + + if (iterations <= MAX_LOOP_ITERATIONS) // Last loop fragment + { + mExcessiveLoopIndex = NULL; // Stops setting the Break flag + } + + // for(int index = initial; index < clampedLimit; index += increment) + + out << "for("; + index->traverse(this); + out << " = "; + out << initial; + + out << "; "; + index->traverse(this); + out << " < "; + out << clampedLimit; + + out << "; "; + index->traverse(this); + out << " += "; + out << increment; + out << ")\n"; + + outputLineDirective(node->getLine().first_line); + out << "{\n"; + + if (node->getBody()) + { + node->getBody()->traverse(this); + } + + outputLineDirective(node->getLine().first_line); + out << ";}\n"; + + if (!firstLoopFragment) + { + out << "}\n"; + } + + firstLoopFragment = false; + + initial += MAX_LOOP_ITERATIONS * increment; + iterations -= MAX_LOOP_ITERATIONS; + } + + out << "}"; + + mExcessiveLoopIndex = restoreIndex; + + return true; + } + else UNIMPLEMENTED(); + } + + return false; // Not handled as an excessive loop +} + +void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString) +{ + TInfoSinkBase &out = mBody; + + if (visit == PreVisit) + { + out << preString; + } + else if (visit == InVisit) + { + out << inString; + } + else if (visit == PostVisit) + { + out << postString; + } +} + +void OutputHLSL::outputLineDirective(int line) +{ + if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0)) + { + mBody << "\n"; + mBody << "#line " << line; + + if (mContext.sourcePath) + { + mBody << " \"" << mContext.sourcePath << "\""; + } + + mBody << "\n"; + } +} + +TString OutputHLSL::argumentString(const TIntermSymbol *symbol) +{ + TQualifier qualifier = symbol->getQualifier(); + const TType &type = symbol->getType(); + TString name = symbol->getSymbol(); + + if (name.empty()) // HLSL demands named arguments, also for prototypes + { + name = "x" + str(mUniqueIndex++); + } + else + { + name = decorate(name); + } + + if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) + { + return qualifierString(qualifier) + " " + textureString(type) + " texture_" + name + arrayString(type) + ", " + + qualifierString(qualifier) + " SamplerState sampler_" + name + arrayString(type); + } + + return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type); +} + +TString OutputHLSL::qualifierString(TQualifier qualifier) +{ + switch(qualifier) + { + case EvqIn: return "in"; + case EvqOut: return "out"; + case EvqInOut: return "inout"; + case EvqConstReadOnly: return "const"; + default: UNREACHABLE(); + } + + return ""; +} + +TString OutputHLSL::typeString(const TType &type) +{ + if (type.getBasicType() == EbtStruct) + { + const TString& typeName = type.getStruct()->name(); + if (typeName != "") + { + return structLookup(typeName); + } + else // Nameless structure, define in place + { + const TFieldList &fields = type.getStruct()->fields(); + + TString string = "struct\n" + "{\n"; + + for (unsigned int i = 0; i < fields.size(); i++) + { + const TField *field = fields[i]; + + string += " " + typeString(*field->type()) + " " + decorate(field->name()) + arrayString(*field->type()) + ";\n"; + } + + string += "} "; + + return string; + } + } + else if (type.isMatrix()) + { + switch (type.getNominalSize()) + { + case 2: return "float2x2"; + case 3: return "float3x3"; + case 4: return "float4x4"; + } + } + else + { + switch (type.getBasicType()) + { + case EbtFloat: + switch (type.getNominalSize()) + { + case 1: return "float"; + case 2: return "float2"; + case 3: return "float3"; + case 4: return "float4"; + } + case EbtInt: + switch (type.getNominalSize()) + { + case 1: return "int"; + case 2: return "int2"; + case 3: return "int3"; + case 4: return "int4"; + } + case EbtBool: + switch (type.getNominalSize()) + { + case 1: return "bool"; + case 2: return "bool2"; + case 3: return "bool3"; + case 4: return "bool4"; + } + case EbtVoid: + return "void"; + case EbtSampler2D: + return "sampler2D"; + case EbtSamplerCube: + return "samplerCUBE"; + case EbtSamplerExternalOES: + return "sampler2D"; + default: + break; + } + } + + UNREACHABLE(); + return ""; +} + +TString OutputHLSL::textureString(const TType &type) +{ + switch (type.getBasicType()) + { + case EbtSampler2D: + return "Texture2D"; + case EbtSamplerCube: + return "TextureCube"; + case EbtSamplerExternalOES: + return "Texture2D"; + default: + break; + } + + UNREACHABLE(); + return ""; +} + +TString OutputHLSL::arrayString(const TType &type) +{ + if (!type.isArray()) + { + return ""; + } + + return "[" + str(type.getArraySize()) + "]"; +} + +TString OutputHLSL::initializer(const TType &type) +{ + TString string; + + size_t size = type.getObjectSize(); + for (size_t component = 0; component < size; component++) + { + string += "0"; + + if (component + 1 < size) + { + string += ", "; + } + } + + return "{" + string + "}"; +} + +void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters) +{ + if (name == "") + { + return; // Nameless structures don't have constructors + } + + if (type.getStruct() && mStructNames.find(decorate(name)) != mStructNames.end()) + { + return; // Already added + } + + TType ctorType = type; + ctorType.clearArrayness(); + ctorType.setPrecision(EbpHigh); + ctorType.setQualifier(EvqTemporary); + + TString ctorName = type.getStruct() ? decorate(name) : name; + + typedef std::vector ParameterArray; + ParameterArray ctorParameters; + + if (type.getStruct()) + { + mStructNames.insert(decorate(name)); + + TString structure; + structure += "struct " + decorate(name) + "\n" + "{\n"; + + const TFieldList &fields = type.getStruct()->fields(); + + for (unsigned int i = 0; i < fields.size(); i++) + { + const TField *field = fields[i]; + + structure += " " + typeString(*field->type()) + " " + decorateField(field->name(), type) + arrayString(*field->type()) + ";\n"; + } + + structure += "};\n"; + + if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structure) == mStructDeclarations.end()) + { + mStructDeclarations.push_back(structure); + } + + for (unsigned int i = 0; i < fields.size(); i++) + { + ctorParameters.push_back(*fields[i]->type()); + } + } + else if (parameters) + { + for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++) + { + ctorParameters.push_back((*parameter)->getAsTyped()->getType()); + } + } + else UNREACHABLE(); + + TString constructor; + + if (ctorType.getStruct()) + { + constructor += ctorName + " " + ctorName + "_ctor("; + } + else // Built-in type + { + constructor += typeString(ctorType) + " " + ctorName + "("; + } + + for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++) + { + const TType &type = ctorParameters[parameter]; + + constructor += typeString(type) + " x" + str(parameter) + arrayString(type); + + if (parameter < ctorParameters.size() - 1) + { + constructor += ", "; + } + } + + constructor += ")\n" + "{\n"; + + if (ctorType.getStruct()) + { + constructor += " " + ctorName + " structure = {"; + } + else + { + constructor += " return " + typeString(ctorType) + "("; + } + + if (ctorType.isMatrix() && ctorParameters.size() == 1) + { + int dim = ctorType.getNominalSize(); + const TType ¶meter = ctorParameters[0]; + + if (parameter.isScalar()) + { + for (int row = 0; row < dim; row++) + { + for (int col = 0; col < dim; col++) + { + constructor += TString((row == col) ? "x0" : "0.0"); + + if (row < dim - 1 || col < dim - 1) + { + constructor += ", "; + } + } + } + } + else if (parameter.isMatrix()) + { + for (int row = 0; row < dim; row++) + { + for (int col = 0; col < dim; col++) + { + if (row < parameter.getNominalSize() && col < parameter.getNominalSize()) + { + constructor += TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]"; + } + else + { + constructor += TString((row == col) ? "1.0" : "0.0"); + } + + if (row < dim - 1 || col < dim - 1) + { + constructor += ", "; + } + } + } + } + else UNREACHABLE(); + } + else + { + size_t remainingComponents = ctorType.getObjectSize(); + size_t parameterIndex = 0; + + while (remainingComponents > 0) + { + const TType ¶meter = ctorParameters[parameterIndex]; + const size_t parameterSize = parameter.getObjectSize(); + bool moreParameters = parameterIndex + 1 < ctorParameters.size(); + + constructor += "x" + str(parameterIndex); + + if (parameter.isScalar()) + { + ASSERT(parameterSize <= remainingComponents); + remainingComponents -= parameterSize; + } + else if (parameter.isVector()) + { + if (remainingComponents == parameterSize || moreParameters) + { + ASSERT(parameterSize <= remainingComponents); + remainingComponents -= parameterSize; + } + else if (remainingComponents < static_cast(parameter.getNominalSize())) + { + switch (remainingComponents) + { + case 1: constructor += ".x"; break; + case 2: constructor += ".xy"; break; + case 3: constructor += ".xyz"; break; + case 4: constructor += ".xyzw"; break; + default: UNREACHABLE(); + } + + remainingComponents = 0; + } + else UNREACHABLE(); + } + else if (parameter.isMatrix() || parameter.getStruct()) + { + ASSERT(remainingComponents == parameterSize || moreParameters); + ASSERT(parameterSize <= remainingComponents); + + remainingComponents -= parameterSize; + } + else UNREACHABLE(); + + if (moreParameters) + { + parameterIndex++; + } + + if (remainingComponents) + { + constructor += ", "; + } + } + } + + if (ctorType.getStruct()) + { + constructor += "};\n" + " return structure;\n" + "}\n"; + } + else + { + constructor += ");\n" + "}\n"; + } + + mConstructors.insert(constructor); +} + +const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion) +{ + TInfoSinkBase &out = mBody; + + if (type.getBasicType() == EbtStruct) + { + out << structLookup(type.getStruct()->name()) + "_ctor("; + + const TFieldList &fields = type.getStruct()->fields(); + + for (size_t i = 0; i < fields.size(); i++) + { + const TType *fieldType = fields[i]->type(); + + constUnion = writeConstantUnion(*fieldType, constUnion); + + if (i != fields.size() - 1) + { + out << ", "; + } + } + + out << ")"; + } + else + { + size_t size = type.getObjectSize(); + bool writeType = size > 1; + + if (writeType) + { + out << typeString(type) << "("; + } + + for (size_t i = 0; i < size; i++, constUnion++) + { + switch (constUnion->getType()) + { + case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, constUnion->getFConst())); break; + case EbtInt: out << constUnion->getIConst(); break; + case EbtBool: out << constUnion->getBConst(); break; + default: UNREACHABLE(); + } + + if (i != size - 1) + { + out << ", "; + } + } + + if (writeType) + { + out << ")"; + } + } + + return constUnion; +} + +TString OutputHLSL::scopeString(unsigned int depthLimit) +{ + TString string; + + for (unsigned int i = 0; i < mScopeBracket.size() && i < depthLimit; i++) + { + string += "_" + str(i); + } + + return string; +} + +TString OutputHLSL::scopedStruct(const TString &typeName) +{ + if (typeName == "") + { + return typeName; + } + + return typeName + scopeString(mScopeDepth); +} + +TString OutputHLSL::structLookup(const TString &typeName) +{ + for (int depth = mScopeDepth; depth >= 0; depth--) + { + TString scopedName = decorate(typeName + scopeString(depth)); + + for (StructNames::iterator structName = mStructNames.begin(); structName != mStructNames.end(); structName++) + { + if (*structName == scopedName) + { + return scopedName; + } + } + } + + UNREACHABLE(); // Should have found a matching constructor + + return typeName; +} + +TString OutputHLSL::decorate(const TString &string) +{ + if (string.compare(0, 3, "gl_") != 0 && string.compare(0, 3, "dx_") != 0) + { + return "_" + string; + } + + return string; +} + +TString OutputHLSL::decorateUniform(const TString &string, const TType &type) +{ + if (type.getBasicType() == EbtSamplerExternalOES) + { + return "ex_" + string; + } + + return decorate(string); +} + +TString OutputHLSL::decorateField(const TString &string, const TType &structure) +{ + if (structure.getStruct()->name().compare(0, 3, "gl_") != 0) + { + return decorate(string); + } + + return string; +} + +TString OutputHLSL::registerString(TIntermSymbol *operand) +{ + ASSERT(operand->getQualifier() == EvqUniform); + + if (IsSampler(operand->getBasicType())) + { + return "s" + str(samplerRegister(operand)); + } + + return "c" + str(uniformRegister(operand)); +} + +int OutputHLSL::samplerRegister(TIntermSymbol *sampler) +{ + const TType &type = sampler->getType(); + ASSERT(IsSampler(type.getBasicType())); + + int index = mSamplerRegister; + mSamplerRegister += sampler->totalRegisterCount(); + + declareUniform(type, sampler->getSymbol(), index); + + return index; +} + +int OutputHLSL::uniformRegister(TIntermSymbol *uniform) +{ + const TType &type = uniform->getType(); + ASSERT(!IsSampler(type.getBasicType())); + + int index = mUniformRegister; + mUniformRegister += uniform->totalRegisterCount(); + + declareUniform(type, uniform->getSymbol(), index); + + return index; +} + +void OutputHLSL::declareUniform(const TType &type, const TString &name, int index) +{ + TStructure *structure = type.getStruct(); + + if (!structure) + { + mActiveUniforms.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), type.getArraySize(), index)); + } + else + { + const TFieldList &fields = structure->fields(); + + if (type.isArray()) + { + int elementIndex = index; + + for (int i = 0; i < type.getArraySize(); i++) + { + for (size_t j = 0; j < fields.size(); j++) + { + const TType &fieldType = *fields[j]->type(); + const TString uniformName = name + "[" + str(i) + "]." + fields[j]->name(); + declareUniform(fieldType, uniformName, elementIndex); + elementIndex += fieldType.totalRegisterCount(); + } + } + } + else + { + int fieldIndex = index; + + for (size_t i = 0; i < fields.size(); i++) + { + const TType &fieldType = *fields[i]->type(); + const TString uniformName = name + "." + fields[i]->name(); + declareUniform(fieldType, uniformName, fieldIndex); + fieldIndex += fieldType.totalRegisterCount(); + } + } + } +} + +GLenum OutputHLSL::glVariableType(const TType &type) +{ + if (type.getBasicType() == EbtFloat) + { + if (type.isScalar()) + { + return GL_FLOAT; + } + else if (type.isVector()) + { + switch(type.getNominalSize()) + { + case 2: return GL_FLOAT_VEC2; + case 3: return GL_FLOAT_VEC3; + case 4: return GL_FLOAT_VEC4; + default: UNREACHABLE(); + } + } + else if (type.isMatrix()) + { + switch(type.getNominalSize()) + { + case 2: return GL_FLOAT_MAT2; + case 3: return GL_FLOAT_MAT3; + case 4: return GL_FLOAT_MAT4; + default: UNREACHABLE(); + } + } + else UNREACHABLE(); + } + else if (type.getBasicType() == EbtInt) + { + if (type.isScalar()) + { + return GL_INT; + } + else if (type.isVector()) + { + switch(type.getNominalSize()) + { + case 2: return GL_INT_VEC2; + case 3: return GL_INT_VEC3; + case 4: return GL_INT_VEC4; + default: UNREACHABLE(); + } + } + else UNREACHABLE(); + } + else if (type.getBasicType() == EbtBool) + { + if (type.isScalar()) + { + return GL_BOOL; + } + else if (type.isVector()) + { + switch(type.getNominalSize()) + { + case 2: return GL_BOOL_VEC2; + case 3: return GL_BOOL_VEC3; + case 4: return GL_BOOL_VEC4; + default: UNREACHABLE(); + } + } + else UNREACHABLE(); + } + else if (type.getBasicType() == EbtSampler2D) + { + return GL_SAMPLER_2D; + } + else if (type.getBasicType() == EbtSamplerCube) + { + return GL_SAMPLER_CUBE; + } + else UNREACHABLE(); + + return GL_NONE; +} + +GLenum OutputHLSL::glVariablePrecision(const TType &type) +{ + if (type.getBasicType() == EbtFloat) + { + switch (type.getPrecision()) + { + case EbpHigh: return GL_HIGH_FLOAT; + case EbpMedium: return GL_MEDIUM_FLOAT; + case EbpLow: return GL_LOW_FLOAT; + case EbpUndefined: + // Should be defined as the default precision by the parser + default: UNREACHABLE(); + } + } + else if (type.getBasicType() == EbtInt) + { + switch (type.getPrecision()) + { + case EbpHigh: return GL_HIGH_INT; + case EbpMedium: return GL_MEDIUM_INT; + case EbpLow: return GL_LOW_INT; + case EbpUndefined: + // Should be defined as the default precision by the parser + default: UNREACHABLE(); + } + } + + // Other types (boolean, sampler) don't have a precision + return GL_NONE; +} + +} diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h new file mode 100644 index 0000000000..3afd8e9ada --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h @@ -0,0 +1,167 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_OUTPUTHLSL_H_ +#define COMPILER_OUTPUTHLSL_H_ + +#include +#include +#include + +#define GL_APICALL +#include + +#include "compiler/translator/intermediate.h" +#include "compiler/translator/ParseContext.h" +#include "compiler/translator/Uniform.h" + +namespace sh +{ +class UnfoldShortCircuit; + +class OutputHLSL : public TIntermTraverser +{ + public: + OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType); + ~OutputHLSL(); + + void output(); + + TInfoSinkBase &getBodyStream(); + const ActiveUniforms &getUniforms(); + + TString typeString(const TType &type); + TString textureString(const TType &type); + static TString qualifierString(TQualifier qualifier); + static TString arrayString(const TType &type); + static TString initializer(const TType &type); + static TString decorate(const TString &string); // Prepends an underscore to avoid naming clashes + static TString decorateUniform(const TString &string, const TType &type); + static TString decorateField(const TString &string, const TType &structure); + + protected: + void header(); + + // Visit AST nodes and output their code to the body stream + void visitSymbol(TIntermSymbol*); + void visitConstantUnion(TIntermConstantUnion*); + bool visitBinary(Visit visit, TIntermBinary*); + bool visitUnary(Visit visit, TIntermUnary*); + bool visitSelection(Visit visit, TIntermSelection*); + bool visitAggregate(Visit visit, TIntermAggregate*); + bool visitLoop(Visit visit, TIntermLoop*); + bool visitBranch(Visit visit, TIntermBranch*); + + void traverseStatements(TIntermNode *node); + bool isSingleStatement(TIntermNode *node); + bool handleExcessiveLoop(TIntermLoop *node); + void outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString); + void outputLineDirective(int line); + TString argumentString(const TIntermSymbol *symbol); + int vectorSize(const TType &type) const; + + void addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters); + const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion); + + TString scopeString(unsigned int depthLimit); + TString scopedStruct(const TString &typeName); + TString structLookup(const TString &typeName); + + TParseContext &mContext; + const ShShaderOutput mOutputType; + UnfoldShortCircuit *mUnfoldShortCircuit; + bool mInsideFunction; + + // Output streams + TInfoSinkBase mHeader; + TInfoSinkBase mBody; + TInfoSinkBase mFooter; + + typedef std::map ReferencedSymbols; + ReferencedSymbols mReferencedUniforms; + ReferencedSymbols mReferencedAttributes; + ReferencedSymbols mReferencedVaryings; + + // Parameters determining what goes in the header output + bool mUsesTexture2D; + bool mUsesTexture2D_bias; + bool mUsesTexture2DLod; + bool mUsesTexture2DProj; + bool mUsesTexture2DProj_bias; + bool mUsesTexture2DProjLod; + bool mUsesTextureCube; + bool mUsesTextureCube_bias; + bool mUsesTextureCubeLod; + bool mUsesTexture2DLod0; + bool mUsesTexture2DLod0_bias; + bool mUsesTexture2DProjLod0; + bool mUsesTexture2DProjLod0_bias; + bool mUsesTextureCubeLod0; + bool mUsesTextureCubeLod0_bias; + bool mUsesFragColor; + bool mUsesFragData; + bool mUsesDepthRange; + bool mUsesFragCoord; + bool mUsesPointCoord; + bool mUsesFrontFacing; + bool mUsesPointSize; + bool mUsesFragDepth; + bool mUsesXor; + bool mUsesMod1; + bool mUsesMod2v; + bool mUsesMod2f; + bool mUsesMod3v; + bool mUsesMod3f; + bool mUsesMod4v; + bool mUsesMod4f; + bool mUsesFaceforward1; + bool mUsesFaceforward2; + bool mUsesFaceforward3; + bool mUsesFaceforward4; + bool mUsesAtan2_1; + bool mUsesAtan2_2; + bool mUsesAtan2_3; + bool mUsesAtan2_4; + bool mUsesDiscardRewriting; + + int mNumRenderTargets; + + typedef std::set Constructors; + Constructors mConstructors; + + typedef std::set StructNames; + StructNames mStructNames; + + typedef std::list StructDeclarations; + StructDeclarations mStructDeclarations; + + typedef std::vector ScopeBracket; + ScopeBracket mScopeBracket; + unsigned int mScopeDepth; + + int mUniqueIndex; // For creating unique names + + bool mContainsLoopDiscontinuity; + bool mOutputLod0Function; + bool mInsideDiscontinuousLoop; + + TIntermSymbol *mExcessiveLoopIndex; + + int mUniformRegister; + int mSamplerRegister; + + TString registerString(TIntermSymbol *operand); + int samplerRegister(TIntermSymbol *sampler); + int uniformRegister(TIntermSymbol *uniform); + void declareUniform(const TType &type, const TString &name, int index); + static GLenum glVariableType(const TType &type); + static GLenum glVariablePrecision(const TType &type); + + ActiveUniforms mActiveUniforms; +}; +} + +#endif // COMPILER_OUTPUTHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp new file mode 100644 index 0000000000..1a1e0d140c --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp @@ -0,0 +1,1602 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/ParseContext.h" + +#include +#include + +#include "compiler/translator/glslang.h" +#include "compiler/preprocessor/SourceLocation.h" + +/////////////////////////////////////////////////////////////////////// +// +// Sub- vector and matrix fields +// +//////////////////////////////////////////////////////////////////////// + +// +// Look at a '.' field selector string and change it into offsets +// for a vector. +// +bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, const TSourceLoc& line) +{ + fields.num = (int) compString.size(); + if (fields.num > 4) { + error(line, "illegal vector field selection", compString.c_str()); + return false; + } + + enum { + exyzw, + ergba, + estpq + } fieldSet[4]; + + for (int i = 0; i < fields.num; ++i) { + switch (compString[i]) { + case 'x': + fields.offsets[i] = 0; + fieldSet[i] = exyzw; + break; + case 'r': + fields.offsets[i] = 0; + fieldSet[i] = ergba; + break; + case 's': + fields.offsets[i] = 0; + fieldSet[i] = estpq; + break; + case 'y': + fields.offsets[i] = 1; + fieldSet[i] = exyzw; + break; + case 'g': + fields.offsets[i] = 1; + fieldSet[i] = ergba; + break; + case 't': + fields.offsets[i] = 1; + fieldSet[i] = estpq; + break; + case 'z': + fields.offsets[i] = 2; + fieldSet[i] = exyzw; + break; + case 'b': + fields.offsets[i] = 2; + fieldSet[i] = ergba; + break; + case 'p': + fields.offsets[i] = 2; + fieldSet[i] = estpq; + break; + + case 'w': + fields.offsets[i] = 3; + fieldSet[i] = exyzw; + break; + case 'a': + fields.offsets[i] = 3; + fieldSet[i] = ergba; + break; + case 'q': + fields.offsets[i] = 3; + fieldSet[i] = estpq; + break; + default: + error(line, "illegal vector field selection", compString.c_str()); + return false; + } + } + + for (int i = 0; i < fields.num; ++i) { + if (fields.offsets[i] >= vecSize) { + error(line, "vector field selection out of range", compString.c_str()); + return false; + } + + if (i > 0) { + if (fieldSet[i] != fieldSet[i-1]) { + error(line, "illegal - vector component fields not from the same set", compString.c_str()); + return false; + } + } + } + + return true; +} + + +// +// Look at a '.' field selector string and change it into offsets +// for a matrix. +// +bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, const TSourceLoc& line) +{ + fields.wholeRow = false; + fields.wholeCol = false; + fields.row = -1; + fields.col = -1; + + if (compString.size() != 2) { + error(line, "illegal length of matrix field selection", compString.c_str()); + return false; + } + + if (compString[0] == '_') { + if (compString[1] < '0' || compString[1] > '3') { + error(line, "illegal matrix field selection", compString.c_str()); + return false; + } + fields.wholeCol = true; + fields.col = compString[1] - '0'; + } else if (compString[1] == '_') { + if (compString[0] < '0' || compString[0] > '3') { + error(line, "illegal matrix field selection", compString.c_str()); + return false; + } + fields.wholeRow = true; + fields.row = compString[0] - '0'; + } else { + if (compString[0] < '0' || compString[0] > '3' || + compString[1] < '0' || compString[1] > '3') { + error(line, "illegal matrix field selection", compString.c_str()); + return false; + } + fields.row = compString[0] - '0'; + fields.col = compString[1] - '0'; + } + + if (fields.row >= matSize || fields.col >= matSize) { + error(line, "matrix field selection out of range", compString.c_str()); + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////// +// +// Errors +// +//////////////////////////////////////////////////////////////////////// + +// +// Track whether errors have occurred. +// +void TParseContext::recover() +{ +} + +// +// Used by flex/bison to output all syntax and parsing errors. +// +void TParseContext::error(const TSourceLoc& loc, + const char* reason, const char* token, + const char* extraInfo) +{ + pp::SourceLocation srcLoc; + srcLoc.file = loc.first_file; + srcLoc.line = loc.first_line; + diagnostics.writeInfo(pp::Diagnostics::PP_ERROR, + srcLoc, reason, token, extraInfo); + +} + +void TParseContext::warning(const TSourceLoc& loc, + const char* reason, const char* token, + const char* extraInfo) { + pp::SourceLocation srcLoc; + srcLoc.file = loc.first_file; + srcLoc.line = loc.first_line; + diagnostics.writeInfo(pp::Diagnostics::PP_WARNING, + srcLoc, reason, token, extraInfo); +} + +void TParseContext::trace(const char* str) +{ + diagnostics.writeDebug(str); +} + +// +// Same error message for all places assignments don't work. +// +void TParseContext::assignError(const TSourceLoc& line, const char* op, TString left, TString right) +{ + std::stringstream extraInfoStream; + extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'"; + std::string extraInfo = extraInfoStream.str(); + error(line, "", op, extraInfo.c_str()); +} + +// +// Same error message for all places unary operations don't work. +// +void TParseContext::unaryOpError(const TSourceLoc& line, const char* op, TString operand) +{ + std::stringstream extraInfoStream; + extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand + << " (or there is no acceptable conversion)"; + std::string extraInfo = extraInfoStream.str(); + error(line, " wrong operand type", op, extraInfo.c_str()); +} + +// +// Same error message for all binary operations don't work. +// +void TParseContext::binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right) +{ + std::stringstream extraInfoStream; + extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left + << "' and a right operand of type '" << right << "' (or there is no acceptable conversion)"; + std::string extraInfo = extraInfoStream.str(); + error(line, " wrong operand types ", op, extraInfo.c_str()); +} + +bool TParseContext::precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type){ + if (!checksPrecisionErrors) + return false; + switch( type ){ + case EbtFloat: + if( precision == EbpUndefined ){ + error( line, "No precision specified for (float)", "" ); + return true; + } + break; + case EbtInt: + if( precision == EbpUndefined ){ + error( line, "No precision specified (int)", "" ); + return true; + } + break; + default: + return false; + } + return false; +} + +// +// Both test and if necessary, spit out an error, to see if the node is really +// an l-value that can be operated on this way. +// +// Returns true if the was an error. +// +bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped* node) +{ + TIntermSymbol* symNode = node->getAsSymbolNode(); + TIntermBinary* binaryNode = node->getAsBinaryNode(); + + if (binaryNode) { + bool errorReturn; + + switch(binaryNode->getOp()) { + case EOpIndexDirect: + case EOpIndexIndirect: + case EOpIndexDirectStruct: + return lValueErrorCheck(line, op, binaryNode->getLeft()); + case EOpVectorSwizzle: + errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft()); + if (!errorReturn) { + int offset[4] = {0,0,0,0}; + + TIntermTyped* rightNode = binaryNode->getRight(); + TIntermAggregate *aggrNode = rightNode->getAsAggregate(); + + for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); + p != aggrNode->getSequence().end(); p++) { + int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0); + offset[value]++; + if (offset[value] > 1) { + error(line, " l-value of swizzle cannot have duplicate components", op); + + return true; + } + } + } + + return errorReturn; + default: + break; + } + error(line, " l-value required", op); + + return true; + } + + + const char* symbol = 0; + if (symNode != 0) + symbol = symNode->getSymbol().c_str(); + + const char* message = 0; + switch (node->getQualifier()) { + case EvqConst: message = "can't modify a const"; break; + case EvqConstReadOnly: message = "can't modify a const"; break; + case EvqAttribute: message = "can't modify an attribute"; break; + case EvqUniform: message = "can't modify a uniform"; break; + case EvqVaryingIn: message = "can't modify a varying"; break; + case EvqFragCoord: message = "can't modify gl_FragCoord"; break; + case EvqFrontFacing: message = "can't modify gl_FrontFacing"; break; + case EvqPointCoord: message = "can't modify gl_PointCoord"; break; + default: + + // + // Type that can't be written to? + // + switch (node->getBasicType()) { + case EbtSampler2D: + case EbtSamplerCube: + message = "can't modify a sampler"; + break; + case EbtVoid: + message = "can't modify void"; + break; + default: + break; + } + } + + if (message == 0 && binaryNode == 0 && symNode == 0) { + error(line, " l-value required", op); + + return true; + } + + + // + // Everything else is okay, no error. + // + if (message == 0) + return false; + + // + // If we get here, we have an error and a message. + // + if (symNode) { + std::stringstream extraInfoStream; + extraInfoStream << "\"" << symbol << "\" (" << message << ")"; + std::string extraInfo = extraInfoStream.str(); + error(line, " l-value required", op, extraInfo.c_str()); + } + else { + std::stringstream extraInfoStream; + extraInfoStream << "(" << message << ")"; + std::string extraInfo = extraInfoStream.str(); + error(line, " l-value required", op, extraInfo.c_str()); + } + + return true; +} + +// +// Both test, and if necessary spit out an error, to see if the node is really +// a constant. +// +// Returns true if the was an error. +// +bool TParseContext::constErrorCheck(TIntermTyped* node) +{ + if (node->getQualifier() == EvqConst) + return false; + + error(node->getLine(), "constant expression required", ""); + + return true; +} + +// +// Both test, and if necessary spit out an error, to see if the node is really +// an integer. +// +// Returns true if the was an error. +// +bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token) +{ + if (node->getBasicType() == EbtInt && node->getNominalSize() == 1) + return false; + + error(node->getLine(), "integer expression required", token); + + return true; +} + +// +// Both test, and if necessary spit out an error, to see if we are currently +// globally scoped. +// +// Returns true if the was an error. +// +bool TParseContext::globalErrorCheck(const TSourceLoc& line, bool global, const char* token) +{ + if (global) + return false; + + error(line, "only allowed at global scope", token); + + return true; +} + +// +// For now, keep it simple: if it starts "gl_", it's reserved, independent +// of scope. Except, if the symbol table is at the built-in push-level, +// which is when we are parsing built-ins. +// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a +// webgl shader. +// +// Returns true if there was an error. +// +bool TParseContext::reservedErrorCheck(const TSourceLoc& line, const TString& identifier) +{ + static const char* reservedErrMsg = "reserved built-in name"; + if (!symbolTable.atBuiltInLevel()) { + if (identifier.compare(0, 3, "gl_") == 0) { + error(line, reservedErrMsg, "gl_"); + return true; + } + if (isWebGLBasedSpec(shaderSpec)) { + if (identifier.compare(0, 6, "webgl_") == 0) { + error(line, reservedErrMsg, "webgl_"); + return true; + } + if (identifier.compare(0, 7, "_webgl_") == 0) { + error(line, reservedErrMsg, "_webgl_"); + return true; + } + if (shaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0) { + error(line, reservedErrMsg, "css_"); + return true; + } + } + if (identifier.find("__") != TString::npos) { + error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str()); + return true; + } + } + + return false; +} + +// +// Make sure there is enough data provided to the constructor to build +// something of the type of the constructor. Also returns the type of +// the constructor. +// +// Returns true if there was an error in construction. +// +bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* node, TFunction& function, TOperator op, TType* type) +{ + *type = function.getReturnType(); + + bool constructingMatrix = false; + switch(op) { + case EOpConstructMat2: + case EOpConstructMat3: + case EOpConstructMat4: + constructingMatrix = true; + break; + default: + break; + } + + // + // Note: It's okay to have too many components available, but not okay to have unused + // arguments. 'full' will go to true when enough args have been seen. If we loop + // again, there is an extra argument, so 'overfull' will become true. + // + + size_t size = 0; + bool constType = true; + bool full = false; + bool overFull = false; + bool matrixInMatrix = false; + bool arrayArg = false; + for (size_t i = 0; i < function.getParamCount(); ++i) { + const TParameter& param = function.getParam(i); + size += param.type->getObjectSize(); + + if (constructingMatrix && param.type->isMatrix()) + matrixInMatrix = true; + if (full) + overFull = true; + if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize()) + full = true; + if (param.type->getQualifier() != EvqConst) + constType = false; + if (param.type->isArray()) + arrayArg = true; + } + + if (constType) + type->setQualifier(EvqConst); + + if (type->isArray() && static_cast(type->getArraySize()) != function.getParamCount()) { + error(line, "array constructor needs one argument per array element", "constructor"); + return true; + } + + if (arrayArg && op != EOpConstructStruct) { + error(line, "constructing from a non-dereferenced array", "constructor"); + return true; + } + + if (matrixInMatrix && !type->isArray()) { + if (function.getParamCount() != 1) { + error(line, "constructing matrix from matrix can only take one argument", "constructor"); + return true; + } + } + + if (overFull) { + error(line, "too many arguments", "constructor"); + return true; + } + + if (op == EOpConstructStruct && !type->isArray() && type->getStruct()->fields().size() != function.getParamCount()) { + error(line, "Number of constructor parameters does not match the number of structure fields", "constructor"); + return true; + } + + if (!type->isMatrix() || !matrixInMatrix) { + if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) || + (op == EOpConstructStruct && size < type->getObjectSize())) { + error(line, "not enough data provided for construction", "constructor"); + return true; + } + } + + TIntermTyped *typed = node ? node->getAsTyped() : 0; + if (typed == 0) { + error(line, "constructor argument does not have a type", "constructor"); + return true; + } + if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) { + error(line, "cannot convert a sampler", "constructor"); + return true; + } + if (typed->getBasicType() == EbtVoid) { + error(line, "cannot convert a void", "constructor"); + return true; + } + + return false; +} + +// This function checks to see if a void variable has been declared and raise an error message for such a case +// +// returns true in case of an error +// +bool TParseContext::voidErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& pubType) +{ + if (pubType.type == EbtVoid) { + error(line, "illegal use of type 'void'", identifier.c_str()); + return true; + } + + return false; +} + +// This function checks to see if the node (for the expression) contains a scalar boolean expression or not +// +// returns true in case of an error +// +bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TIntermTyped* type) +{ + if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) { + error(line, "boolean expression expected", ""); + return true; + } + + return false; +} + +// This function checks to see if the node (for the expression) contains a scalar boolean expression or not +// +// returns true in case of an error +// +bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TPublicType& pType) +{ + if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) { + error(line, "boolean expression expected", ""); + return true; + } + + return false; +} + +bool TParseContext::samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason) +{ + if (pType.type == EbtStruct) { + if (containsSampler(*pType.userDef)) { + error(line, reason, getBasicString(pType.type), "(structure contains a sampler)"); + + return true; + } + + return false; + } else if (IsSampler(pType.type)) { + error(line, reason, getBasicString(pType.type)); + + return true; + } + + return false; +} + +bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType) +{ + if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) && + pType.type == EbtStruct) { + error(line, "cannot be used with a structure", getQualifierString(pType.qualifier)); + + return true; + } + + if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform")) + return true; + + return false; +} + +bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type) +{ + if ((qualifier == EvqOut || qualifier == EvqInOut) && + type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) { + error(line, "samplers cannot be output parameters", type.getBasicString()); + return true; + } + + return false; +} + +bool TParseContext::containsSampler(TType& type) +{ + if (IsSampler(type.getBasicType())) + return true; + + if (type.getBasicType() == EbtStruct) { + const TFieldList& fields = type.getStruct()->fields(); + for (unsigned int i = 0; i < fields.size(); ++i) { + if (containsSampler(*fields[i]->type())) + return true; + } + } + + return false; +} + +// +// Do size checking for an array type's size. +// +// Returns true if there was an error. +// +bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size) +{ + TIntermConstantUnion* constant = expr->getAsConstantUnion(); + if (constant == 0 || constant->getBasicType() != EbtInt) { + error(line, "array size must be a constant integer expression", ""); + return true; + } + + size = constant->getIConst(0); + + if (size <= 0) { + error(line, "array size must be a positive integer", ""); + size = 1; + return true; + } + + return false; +} + +// +// See if this qualifier can be an array. +// +// Returns true if there is an error. +// +bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type) +{ + if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) { + error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str()); + return true; + } + + return false; +} + +// +// See if this type can be an array. +// +// Returns true if there is an error. +// +bool TParseContext::arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type) +{ + // + // Can the type be an array? + // + if (type.array) { + error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str()); + return true; + } + + return false; +} + +// +// Do all the semantic checking for declaring an array, with and +// without a size, and make the right changes to the symbol table. +// +// size == 0 means no specified size. +// +// Returns true if there was an error. +// +bool TParseContext::arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable) +{ + // + // Don't check for reserved word use until after we know it's not in the symbol table, + // because reserved arrays can be redeclared. + // + + bool builtIn = false; + bool sameScope = false; + TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope); + if (symbol == 0 || !sameScope) { + if (reservedErrorCheck(line, identifier)) + return true; + + variable = new TVariable(&identifier, TType(type)); + + if (type.arraySize) + variable->getType().setArraySize(type.arraySize); + + if (! symbolTable.insert(*variable)) { + delete variable; + error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str()); + return true; + } + } else { + if (! symbol->isVariable()) { + error(line, "variable expected", identifier.c_str()); + return true; + } + + variable = static_cast(symbol); + if (! variable->getType().isArray()) { + error(line, "redeclaring non-array as array", identifier.c_str()); + return true; + } + if (variable->getType().getArraySize() > 0) { + error(line, "redeclaration of array with size", identifier.c_str()); + return true; + } + + if (! variable->getType().sameElementType(TType(type))) { + error(line, "redeclaration of array with a different type", identifier.c_str()); + return true; + } + + if (type.arraySize) + variable->getType().setArraySize(type.arraySize); + } + + if (voidErrorCheck(line, identifier, type)) + return true; + + return false; +} + +// +// Enforce non-initializer type/qualifier rules. +// +// Returns true if there was an error. +// +bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array) +{ + if (type.qualifier == EvqConst) + { + // Make the qualifier make sense. + type.qualifier = EvqTemporary; + + if (array) + { + error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str()); + } + else if (type.isStructureContainingArrays()) + { + error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str()); + } + else + { + error(line, "variables with qualifier 'const' must be initialized", identifier.c_str()); + } + + return true; + } + + return false; +} + +// +// Do semantic checking for a variable declaration that has no initializer, +// and update the symbol table. +// +// Returns true if there was an error. +// +bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable) +{ + if (reservedErrorCheck(line, identifier)) + recover(); + + variable = new TVariable(&identifier, TType(type)); + + if (! symbolTable.insert(*variable)) { + error(line, "redefinition", variable->getName().c_str()); + delete variable; + variable = 0; + return true; + } + + if (voidErrorCheck(line, identifier, type)) + return true; + + return false; +} + +bool TParseContext::paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type) +{ + if (qualifier != EvqConst && qualifier != EvqTemporary) { + error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier)); + return true; + } + if (qualifier == EvqConst && paramQualifier != EvqIn) { + error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier)); + return true; + } + + if (qualifier == EvqConst) + type->setQualifier(EvqConstReadOnly); + else + type->setQualifier(paramQualifier); + + return false; +} + +bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& extension) +{ + const TExtensionBehavior& extBehavior = extensionBehavior(); + TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str()); + if (iter == extBehavior.end()) { + error(line, "extension", extension.c_str(), "is not supported"); + return true; + } + // In GLSL ES, an extension's default behavior is "disable". + if (iter->second == EBhDisable || iter->second == EBhUndefined) { + error(line, "extension", extension.c_str(), "is disabled"); + return true; + } + if (iter->second == EBhWarn) { + warning(line, "extension", extension.c_str(), "is being used"); + return false; + } + + return false; +} + +bool TParseContext::supportsExtension(const char* extension) +{ + const TExtensionBehavior& extbehavior = extensionBehavior(); + TExtensionBehavior::const_iterator iter = extbehavior.find(extension); + return (iter != extbehavior.end()); +} + +bool TParseContext::isExtensionEnabled(const char* extension) const +{ + const TExtensionBehavior& extbehavior = extensionBehavior(); + TExtensionBehavior::const_iterator iter = extbehavior.find(extension); + + if (iter == extbehavior.end()) + { + return false; + } + + return (iter->second == EBhEnable || iter->second == EBhRequire); +} + +///////////////////////////////////////////////////////////////////////////////// +// +// Non-Errors. +// +///////////////////////////////////////////////////////////////////////////////// + +// +// Look up a function name in the symbol table, and make sure it is a function. +// +// Return the function symbol if found, otherwise 0. +// +const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, bool *builtIn) +{ + // First find by unmangled name to check whether the function name has been + // hidden by a variable name or struct typename. + // If a function is found, check for one with a matching argument list. + const TSymbol* symbol = symbolTable.find(call->getName(), builtIn); + if (symbol == 0 || symbol->isFunction()) { + symbol = symbolTable.find(call->getMangledName(), builtIn); + } + + if (symbol == 0) { + error(line, "no matching overloaded function found", call->getName().c_str()); + return 0; + } + + if (!symbol->isFunction()) { + error(line, "function name expected", call->getName().c_str()); + return 0; + } + + return static_cast(symbol); +} + +// +// Initializers show up in several places in the grammar. Have one set of +// code to handle them here. +// +bool TParseContext::executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType, + TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) +{ + TType type = TType(pType); + + if (variable == 0) { + if (reservedErrorCheck(line, identifier)) + return true; + + if (voidErrorCheck(line, identifier, pType)) + return true; + + // + // add variable to symbol table + // + variable = new TVariable(&identifier, type); + if (! symbolTable.insert(*variable)) { + error(line, "redefinition", variable->getName().c_str()); + return true; + // don't delete variable, it's used by error recovery, and the pool + // pop will take care of the memory + } + } + + // + // identifier must be of type constant, a global, or a temporary + // + TQualifier qualifier = variable->getType().getQualifier(); + if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) { + error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString()); + return true; + } + // + // test for and propagate constant + // + + if (qualifier == EvqConst) { + if (qualifier != initializer->getType().getQualifier()) { + std::stringstream extraInfoStream; + extraInfoStream << "'" << variable->getType().getCompleteString() << "'"; + std::string extraInfo = extraInfoStream.str(); + error(line, " assigning non-constant to", "=", extraInfo.c_str()); + variable->getType().setQualifier(EvqTemporary); + return true; + } + if (type != initializer->getType()) { + error(line, " non-matching types for const initializer ", + variable->getType().getQualifierString()); + variable->getType().setQualifier(EvqTemporary); + return true; + } + if (initializer->getAsConstantUnion()) { + variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); + } else if (initializer->getAsSymbolNode()) { + const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol()); + const TVariable* tVar = static_cast(symbol); + + ConstantUnion* constArray = tVar->getConstPointer(); + variable->shareConstPointer(constArray); + } else { + std::stringstream extraInfoStream; + extraInfoStream << "'" << variable->getType().getCompleteString() << "'"; + std::string extraInfo = extraInfoStream.str(); + error(line, " cannot assign to", "=", extraInfo.c_str()); + variable->getType().setQualifier(EvqTemporary); + return true; + } + } + + if (qualifier != EvqConst) { + TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line); + intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line); + if (intermNode == 0) { + assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); + return true; + } + } else + intermNode = 0; + + return false; +} + +bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) +{ + ASSERT(aggrNode != NULL); + if (!aggrNode->isConstructor()) + return false; + + bool allConstant = true; + + // check if all the child nodes are constants so that they can be inserted into + // the parent node + TIntermSequence &sequence = aggrNode->getSequence() ; + for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) { + if (!(*p)->getAsTyped()->getAsConstantUnion()) + return false; + } + + return allConstant; +} + +// This function is used to test for the correctness of the parameters passed to various constructor functions +// and also convert them to the right datatype if it is allowed and required. +// +// Returns 0 for an error or the constructed node (aggregate or typed) for no error. +// +TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc& line) +{ + if (node == 0) + return 0; + + TIntermAggregate* aggrNode = node->getAsAggregate(); + + TFieldList::const_iterator memberFields; + if (op == EOpConstructStruct) + memberFields = type->getStruct()->fields().begin(); + + TType elementType = *type; + if (type->isArray()) + elementType.clearArrayness(); + + bool singleArg; + if (aggrNode) { + if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1) + singleArg = true; + else + singleArg = false; + } else + singleArg = true; + + TIntermTyped *newNode; + if (singleArg) { + // If structure constructor or array constructor is being called + // for only one parameter inside the structure, we need to call constructStruct function once. + if (type->isArray()) + newNode = constructStruct(node, &elementType, 1, node->getLine(), false); + else if (op == EOpConstructStruct) + newNode = constructStruct(node, (*memberFields)->type(), 1, node->getLine(), false); + else + newNode = constructBuiltIn(type, op, node, node->getLine(), false); + + if (newNode && newNode->getAsAggregate()) { + TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type); + if (constConstructor) + return constConstructor; + } + + return newNode; + } + + // + // Handle list of arguments. + // + TIntermSequence &sequenceVector = aggrNode->getSequence() ; // Stores the information about the parameter to the constructor + // if the structure constructor contains more than one parameter, then construct + // each parameter + + int paramCount = 0; // keeps a track of the constructor parameter number being checked + + // for each parameter to the constructor call, check to see if the right type is passed or convert them + // to the right type if possible (and allowed). + // for structure constructors, just check if the right type is passed, no conversion is allowed. + + for (TIntermSequence::iterator p = sequenceVector.begin(); + p != sequenceVector.end(); p++, paramCount++) { + if (type->isArray()) + newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true); + else if (op == EOpConstructStruct) + newNode = constructStruct(*p, memberFields[paramCount]->type(), paramCount+1, node->getLine(), true); + else + newNode = constructBuiltIn(type, op, *p, node->getLine(), true); + + if (newNode) { + *p = newNode; + } + } + + TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line); + TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type); + if (constConstructor) + return constConstructor; + + return constructor; +} + +TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type) +{ + bool canBeFolded = areAllChildConst(aggrNode); + aggrNode->setType(type); + if (canBeFolded) { + bool returnVal = false; + ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()]; + if (aggrNode->getSequence().size() == 1) { + returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type, true); + } + else { + returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type); + } + if (returnVal) + return 0; + + return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine()); + } + + return 0; +} + +// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value +// for the parameter to the constructor (passed to this function). Essentially, it converts +// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a +// float, then float is converted to int. +// +// Returns 0 for an error or the constructed node. +// +TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, const TSourceLoc& line, bool subset) +{ + TIntermTyped* newNode; + TOperator basicOp; + + // + // First, convert types as needed. + // + switch (op) { + case EOpConstructVec2: + case EOpConstructVec3: + case EOpConstructVec4: + case EOpConstructMat2: + case EOpConstructMat3: + case EOpConstructMat4: + case EOpConstructFloat: + basicOp = EOpConstructFloat; + break; + + case EOpConstructIVec2: + case EOpConstructIVec3: + case EOpConstructIVec4: + case EOpConstructInt: + basicOp = EOpConstructInt; + break; + + case EOpConstructBVec2: + case EOpConstructBVec3: + case EOpConstructBVec4: + case EOpConstructBool: + basicOp = EOpConstructBool; + break; + + default: + error(line, "unsupported construction", ""); + recover(); + + return 0; + } + newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable); + if (newNode == 0) { + error(line, "can't convert", "constructor"); + return 0; + } + + // + // Now, if there still isn't an operation to do the construction, and we need one, add one. + // + + // Otherwise, skip out early. + if (subset || (newNode != node && newNode->getType() == *type)) + return newNode; + + // setAggregateOperator will insert a new node for the constructor, as needed. + return intermediate.setAggregateOperator(newNode, op, line); +} + +// This function tests for the type of the parameters to the structures constructors. Raises +// an error message if the expected type does not match the parameter passed to the constructor. +// +// Returns 0 for an error or the input node itself if the expected and the given parameter types match. +// +TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, const TSourceLoc& line, bool subset) +{ + if (*type == node->getAsTyped()->getType()) { + if (subset) + return node->getAsTyped(); + else + return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line); + } else { + std::stringstream extraInfoStream; + extraInfoStream << "cannot convert parameter " << paramCount + << " from '" << node->getAsTyped()->getType().getBasicString() + << "' to '" << type->getBasicString() << "'"; + std::string extraInfo = extraInfoStream.str(); + error(line, "", "constructor", extraInfo.c_str()); + recover(); + } + + return 0; +} + +// +// This function returns the tree representation for the vector field(s) being accessed from contant vector. +// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is +// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol +// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of +// a constant matrix. +// +TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line) +{ + TIntermTyped* typedNode; + TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); + + ConstantUnion *unionArray; + if (tempConstantNode) { + unionArray = tempConstantNode->getUnionArrayPointer(); + + if (!unionArray) { + return node; + } + } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error + error(line, "Cannot offset into the vector", "Error"); + recover(); + + return 0; + } + + ConstantUnion* constArray = new ConstantUnion[fields.num]; + + for (int i = 0; i < fields.num; i++) { + if (fields.offsets[i] >= node->getType().getNominalSize()) { + std::stringstream extraInfoStream; + extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'"; + std::string extraInfo = extraInfoStream.str(); + error(line, "", "[", extraInfo.c_str()); + recover(); + fields.offsets[i] = 0; + } + + constArray[i] = unionArray[fields.offsets[i]]; + + } + typedNode = intermediate.addConstantUnion(constArray, node->getType(), line); + return typedNode; +} + +// +// This function returns the column being accessed from a constant matrix. The values are retrieved from +// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input +// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a +// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure) +// +TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line) +{ + TIntermTyped* typedNode; + TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); + + if (index >= node->getType().getNominalSize()) { + std::stringstream extraInfoStream; + extraInfoStream << "matrix field selection out of range '" << index << "'"; + std::string extraInfo = extraInfoStream.str(); + error(line, "", "[", extraInfo.c_str()); + recover(); + index = 0; + } + + if (tempConstantNode) { + ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); + int size = tempConstantNode->getType().getNominalSize(); + typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line); + } else { + error(line, "Cannot offset into the matrix", "Error"); + recover(); + + return 0; + } + + return typedNode; +} + + +// +// This function returns an element of an array accessed from a constant array. The values are retrieved from +// the symbol table and parse-tree is built for the type of the element. The input +// to the function could either be a symbol node (a[0] where a is a constant array)that represents a +// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure) +// +TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line) +{ + TIntermTyped* typedNode; + TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); + TType arrayElementType = node->getType(); + arrayElementType.clearArrayness(); + + if (index >= node->getType().getArraySize()) { + std::stringstream extraInfoStream; + extraInfoStream << "array field selection out of range '" << index << "'"; + std::string extraInfo = extraInfoStream.str(); + error(line, "", "[", extraInfo.c_str()); + recover(); + index = 0; + } + + if (tempConstantNode) { + size_t arrayElementSize = arrayElementType.getObjectSize(); + ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); + typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line); + } else { + error(line, "Cannot offset into the array", "Error"); + recover(); + + return 0; + } + + return typedNode; +} + + +// +// This function returns the value of a particular field inside a constant structure from the symbol table. +// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr +// function and returns the parse-tree with the values of the embedded/nested struct. +// +TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, const TSourceLoc& line) +{ + const TFieldList& fields = node->getType().getStruct()->fields(); + + size_t instanceSize = 0; + for (size_t index = 0; index < fields.size(); ++index) { + if (fields[index]->name() == identifier) { + break; + } else { + instanceSize += fields[index]->type()->getObjectSize(); + } + } + + TIntermTyped* typedNode = 0; + TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); + if (tempConstantNode) { + ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer(); + + typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function + } else { + error(line, "Cannot offset into the structure", "Error"); + recover(); + + return 0; + } + + return typedNode; +} + +bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier) +{ + ++structNestingLevel; + + // Embedded structure definitions are not supported per GLSL ES spec. + // They aren't allowed in GLSL either, but we need to detect this here + // so we don't rely on the GLSL compiler to catch it. + if (structNestingLevel > 1) { + error(line, "", "Embedded struct definitions are not allowed"); + return true; + } + + return false; +} + +void TParseContext::exitStructDeclaration() +{ + --structNestingLevel; +} + +namespace { + +const int kWebGLMaxStructNesting = 4; + +} // namespace + +bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field) +{ + if (!isWebGLBasedSpec(shaderSpec)) { + return false; + } + + if (field.type()->getBasicType() != EbtStruct) { + return false; + } + + // We're already inside a structure definition at this point, so add + // one to the field's struct nesting. + if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) { + std::stringstream reasonStream; + reasonStream << "Reference of struct type " + << field.type()->getStruct()->name().c_str() + << " exceeds maximum allowed nesting level of " + << kWebGLMaxStructNesting; + std::string reason = reasonStream.str(); + error(line, reason.c_str(), field.name().c_str(), ""); + return true; + } + + return false; +} + +// +// Parse an array index expression +// +TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression) +{ + TIntermTyped *indexedExpression = NULL; + + if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector()) + { + if (baseExpression->getAsSymbolNode()) + { + error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str()); + } + else + { + error(location, " left of '[' is not of type array, matrix, or vector ", "expression"); + } + recover(); + } + + if (indexExpression->getQualifier() == EvqConst) + { + int index = indexExpression->getAsConstantUnion()->getIConst(0); + if (index < 0) + { + std::stringstream infoStream; + infoStream << index; + std::string info = infoStream.str(); + error(location, "negative index", info.c_str()); + recover(); + index = 0; + } + if (baseExpression->getType().getQualifier() == EvqConst) + { + if (baseExpression->isArray()) + { + // constant folding for arrays + indexedExpression = addConstArrayNode(index, baseExpression, location); + } + else if (baseExpression->isVector()) + { + // constant folding for vectors + TVectorFields fields; + fields.num = 1; + fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array + indexedExpression = addConstVectorNode(fields, baseExpression, location); + } + else if (baseExpression->isMatrix()) + { + // constant folding for matrices + indexedExpression = addConstMatrixNode(index, baseExpression, location); + } + } + else + { + if (baseExpression->isArray()) + { + if (index >= baseExpression->getType().getArraySize()) + { + std::stringstream extraInfoStream; + extraInfoStream << "array index out of range '" << index << "'"; + std::string extraInfo = extraInfoStream.str(); + error(location, "", "[", extraInfo.c_str()); + recover(); + index = baseExpression->getType().getArraySize() - 1; + } + else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers")) + { + error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled"); + recover(); + index = 0; + } + } + else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index) + { + std::stringstream extraInfoStream; + extraInfoStream << "field selection out of range '" << index << "'"; + std::string extraInfo = extraInfoStream.str(); + error(location, "", "[", extraInfo.c_str()); + recover(); + index = baseExpression->getType().getNominalSize() - 1; + } + + indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index); + indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location); + } + } + else + { + indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location); + } + + if (indexedExpression == 0) + { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setFConst(0.0f); + indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location); + } + else if (baseExpression->isArray()) + { + const TType &baseType = baseExpression->getType(); + if (baseType.getStruct()) + { + TType copyOfType(baseType.getStruct()); + indexedExpression->setType(copyOfType); + } + else + { + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->isMatrix())); + } + + if (baseExpression->getType().getQualifier() == EvqConst) + { + indexedExpression->getTypePointer()->setQualifier(EvqConst); + } + } + else if (baseExpression->isMatrix()) + { + TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary; + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getNominalSize())); + } + else if (baseExpression->isVector()) + { + TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary; + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier)); + } + else + { + indexedExpression->setType(baseExpression->getType()); + } + + return indexedExpression; +} + +// +// Parse an array of strings using yyparse. +// +// Returns 0 for success. +// +int PaParseStrings(size_t count, const char* const string[], const int length[], + TParseContext* context) { + if ((count == 0) || (string == NULL)) + return 1; + + if (glslang_initialize(context)) + return 1; + + int error = glslang_scan(count, string, length, context); + if (!error) + error = glslang_parse(context); + + glslang_finalize(context); + + return (error == 0) && (context->numErrors() == 0) ? 0 : 1; +} + + + diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.h b/src/3rdparty/angle/src/compiler/translator/ParseContext.h new file mode 100644 index 0000000000..b324e575d3 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.h @@ -0,0 +1,134 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +#ifndef _PARSER_HELPER_INCLUDED_ +#define _PARSER_HELPER_INCLUDED_ + +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/DirectiveHandler.h" +#include "compiler/translator/localintermediate.h" +#include "compiler/preprocessor/Preprocessor.h" +#include "compiler/translator/ShHandle.h" +#include "compiler/translator/SymbolTable.h" + +struct TMatrixFields { + bool wholeRow; + bool wholeCol; + int row; + int col; +}; + +// +// The following are extra variables needed during parsing, grouped together so +// they can be passed to the parser without needing a global. +// +struct TParseContext { + TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, ShShaderType type, ShShaderSpec spec, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) : + intermediate(interm), + symbolTable(symt), + shaderType(type), + shaderSpec(spec), + compileOptions(options), + sourcePath(sourcePath), + treeRoot(0), + loopNestingLevel(0), + structNestingLevel(0), + currentFunctionType(NULL), + functionReturnsValue(false), + checksPrecisionErrors(checksPrecErrors), + diagnostics(is), + directiveHandler(ext, diagnostics), + preprocessor(&diagnostics, &directiveHandler), + scanner(NULL) { } + TIntermediate& intermediate; // to hold and build a parse tree + TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed + ShShaderType shaderType; // vertex or fragment language (future: pack or unpack) + ShShaderSpec shaderSpec; // The language specification compiler conforms to - GLES2 or WebGL. + int compileOptions; + const char* sourcePath; // Path of source file or NULL. + TIntermNode* treeRoot; // root of parse tree being created + int loopNestingLevel; // 0 if outside all loops + int structNestingLevel; // incremented while parsing a struct declaration + const TType* currentFunctionType; // the return type of the function that's currently being parsed + bool functionReturnsValue; // true if a non-void function has a return + bool checksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit. + bool fragmentPrecisionHigh; // true if highp precision is supported in the fragment language. + TString HashErrMsg; + TDiagnostics diagnostics; + TDirectiveHandler directiveHandler; + pp::Preprocessor preprocessor; + void* scanner; + + int numErrors() const { return diagnostics.numErrors(); } + TInfoSink& infoSink() { return diagnostics.infoSink(); } + void error(const TSourceLoc& loc, const char *reason, const char* token, + const char* extraInfo=""); + void warning(const TSourceLoc& loc, const char* reason, const char* token, + const char* extraInfo=""); + void trace(const char* str); + void recover(); + + bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc& line); + bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, const TSourceLoc& line); + + bool reservedErrorCheck(const TSourceLoc& line, const TString& identifier); + void assignError(const TSourceLoc& line, const char* op, TString left, TString right); + void unaryOpError(const TSourceLoc& line, const char* op, TString operand); + void binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right); + bool precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type); + bool lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped*); + bool constErrorCheck(TIntermTyped* node); + bool integerErrorCheck(TIntermTyped* node, const char* token); + bool globalErrorCheck(const TSourceLoc& line, bool global, const char* token); + bool constructorErrorCheck(const TSourceLoc& line, TIntermNode*, TFunction&, TOperator, TType*); + bool arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size); + bool arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type); + bool arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type); + bool arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable); + bool voidErrorCheck(const TSourceLoc&, const TString&, const TPublicType&); + bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*); + bool boolErrorCheck(const TSourceLoc&, const TPublicType&); + bool samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason); + bool structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType); + bool parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type); + bool nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array); + bool nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable); + bool paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type); + bool extensionErrorCheck(const TSourceLoc& line, const TString&); + + const TPragma& pragma() const { return directiveHandler.pragma(); } + const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); } + bool supportsExtension(const char* extension); + bool isExtensionEnabled(const char* extension) const; + + bool containsSampler(TType& type); + bool areAllChildConst(TIntermAggregate* aggrNode); + const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, bool *builtIn = 0); + bool executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType, + TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0); + + TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&); + TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type); + TIntermTyped* constructStruct(TIntermNode*, TType*, int, const TSourceLoc&, bool subset); + TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, const TSourceLoc&, bool subset); + TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&); + TIntermTyped* addConstMatrixNode(int , TIntermTyped*, const TSourceLoc&); + TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line); + TIntermTyped* addConstStruct(TString& , TIntermTyped*, const TSourceLoc&); + TIntermTyped* addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression); + + // Performs an error check for embedded struct declarations. + // Returns true if an error was raised due to the declaration of + // this struct. + bool enterStructDeclaration(const TSourceLoc& line, const TString& identifier); + void exitStructDeclaration(); + + bool structNestingErrorCheck(const TSourceLoc& line, const TField& field); +}; + +int PaParseStrings(size_t count, const char* const string[], const int length[], + TParseContext* context); + +#endif // _PARSER_HELPER_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp new file mode 100644 index 0000000000..abe70262f2 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp @@ -0,0 +1,294 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/PoolAlloc.h" + +#ifndef _MSC_VER +#include +#endif +#include + +#include "common/angleutils.h" +#include "compiler/translator/InitializeGlobals.h" +#include "compiler/translator/osinclude.h" + +OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX; + +bool InitializePoolIndex() +{ + assert(PoolIndex == OS_INVALID_TLS_INDEX); + + PoolIndex = OS_AllocTLSIndex(); + return PoolIndex != OS_INVALID_TLS_INDEX; +} + +void FreePoolIndex() +{ + assert(PoolIndex != OS_INVALID_TLS_INDEX); + + OS_FreeTLSIndex(PoolIndex); + PoolIndex = OS_INVALID_TLS_INDEX; +} + +TPoolAllocator* GetGlobalPoolAllocator() +{ + assert(PoolIndex != OS_INVALID_TLS_INDEX); + return static_cast(OS_GetTLSValue(PoolIndex)); +} + +void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator) +{ + assert(PoolIndex != OS_INVALID_TLS_INDEX); + OS_SetTLSValue(PoolIndex, poolAllocator); +} + +// +// Implement the functionality of the TPoolAllocator class, which +// is documented in PoolAlloc.h. +// +TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) : + pageSize(growthIncrement), + alignment(allocationAlignment), + freeList(0), + inUseList(0), + numCalls(0), + totalBytes(0) +{ + // + // Don't allow page sizes we know are smaller than all common + // OS page sizes. + // + if (pageSize < 4*1024) + pageSize = 4*1024; + + // + // A large currentPageOffset indicates a new page needs to + // be obtained to allocate memory. + // + currentPageOffset = pageSize; + + // + // Adjust alignment to be at least pointer aligned and + // power of 2. + // + size_t minAlign = sizeof(void*); + alignment &= ~(minAlign - 1); + if (alignment < minAlign) + alignment = minAlign; + size_t a = 1; + while (a < alignment) + a <<= 1; + alignment = a; + alignmentMask = a - 1; + + // + // Align header skip + // + headerSkip = minAlign; + if (headerSkip < sizeof(tHeader)) { + headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask; + } +} + +TPoolAllocator::~TPoolAllocator() +{ + while (inUseList) { + tHeader* next = inUseList->nextPage; + inUseList->~tHeader(); + delete [] reinterpret_cast(inUseList); + inUseList = next; + } + + // We should not check the guard blocks + // here, because we did it already when the block was + // placed into the free list. + // + while (freeList) { + tHeader* next = freeList->nextPage; + delete [] reinterpret_cast(freeList); + freeList = next; + } +} + +// Support MSVC++ 6.0 +const unsigned char TAllocation::guardBlockBeginVal = 0xfb; +const unsigned char TAllocation::guardBlockEndVal = 0xfe; +const unsigned char TAllocation::userDataFill = 0xcd; + +#ifdef GUARD_BLOCKS + const size_t TAllocation::guardBlockSize = 16; +#else + const size_t TAllocation::guardBlockSize = 0; +#endif + +// +// Check a single guard block for damage +// +void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const +{ +#ifdef GUARD_BLOCKS + for (size_t x = 0; x < guardBlockSize; x++) { + if (blockMem[x] != val) { + char assertMsg[80]; + + // We don't print the assert message. It's here just to be helpful. +#if defined(_MSC_VER) + snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %Iu byte allocation at 0x%p\n", + locText, size, data()); +#else + snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n", + locText, size, data()); +#endif + assert(0 && "PoolAlloc: Damage in guard block"); + } + } +#endif +} + + +void TPoolAllocator::push() +{ + tAllocState state = { currentPageOffset, inUseList }; + + stack.push_back(state); + + // + // Indicate there is no current page to allocate from. + // + currentPageOffset = pageSize; +} + +// +// Do a mass-deallocation of all the individual allocations +// that have occurred since the last push(), or since the +// last pop(), or since the object's creation. +// +// The deallocated pages are saved for future allocations. +// +void TPoolAllocator::pop() +{ + if (stack.size() < 1) + return; + + tHeader* page = stack.back().page; + currentPageOffset = stack.back().offset; + + while (inUseList != page) { + // invoke destructor to free allocation list + inUseList->~tHeader(); + + tHeader* nextInUse = inUseList->nextPage; + if (inUseList->pageCount > 1) + delete [] reinterpret_cast(inUseList); + else { + inUseList->nextPage = freeList; + freeList = inUseList; + } + inUseList = nextInUse; + } + + stack.pop_back(); +} + +// +// Do a mass-deallocation of all the individual allocations +// that have occurred. +// +void TPoolAllocator::popAll() +{ + while (stack.size() > 0) + pop(); +} + +void* TPoolAllocator::allocate(size_t numBytes) +{ + // + // Just keep some interesting statistics. + // + ++numCalls; + totalBytes += numBytes; + + // If we are using guard blocks, all allocations are bracketed by + // them: [guardblock][allocation][guardblock]. numBytes is how + // much memory the caller asked for. allocationSize is the total + // size including guard blocks. In release build, + // guardBlockSize=0 and this all gets optimized away. + size_t allocationSize = TAllocation::allocationSize(numBytes); + // Detect integer overflow. + if (allocationSize < numBytes) + return 0; + + // + // Do the allocation, most likely case first, for efficiency. + // This step could be moved to be inline sometime. + // + if (allocationSize <= pageSize - currentPageOffset) { + // + // Safe to allocate from currentPageOffset. + // + unsigned char* memory = reinterpret_cast(inUseList) + currentPageOffset; + currentPageOffset += allocationSize; + currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask; + + return initializeAllocation(inUseList, memory, numBytes); + } + + if (allocationSize > pageSize - headerSkip) { + // + // Do a multi-page allocation. Don't mix these with the others. + // The OS is efficient and allocating and free-ing multiple pages. + // + size_t numBytesToAlloc = allocationSize + headerSkip; + // Detect integer overflow. + if (numBytesToAlloc < allocationSize) + return 0; + + tHeader* memory = reinterpret_cast(::new char[numBytesToAlloc]); + if (memory == 0) + return 0; + + // Use placement-new to initialize header + new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize); + inUseList = memory; + + currentPageOffset = pageSize; // make next allocation come from a new page + + // No guard blocks for multi-page allocations (yet) + return reinterpret_cast(reinterpret_cast(memory) + headerSkip); + } + + // + // Need a simple page to allocate from. + // + tHeader* memory; + if (freeList) { + memory = freeList; + freeList = freeList->nextPage; + } else { + memory = reinterpret_cast(::new char[pageSize]); + if (memory == 0) + return 0; + } + + // Use placement-new to initialize header + new(memory) tHeader(inUseList, 1); + inUseList = memory; + + unsigned char* ret = reinterpret_cast(inUseList) + headerSkip; + currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask; + + return initializeAllocation(inUseList, ret, numBytes); +} + + +// +// Check all allocations in a list for damage by calling check on each. +// +void TAllocation::checkAllocList() const +{ + for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc) + alloc->check(); +} diff --git a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h new file mode 100644 index 0000000000..edd249c4d3 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h @@ -0,0 +1,300 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _POOLALLOC_INCLUDED_ +#define _POOLALLOC_INCLUDED_ + +#ifdef _DEBUG +#define GUARD_BLOCKS // define to enable guard block sanity checking +#endif + +// +// This header defines an allocator that can be used to efficiently +// allocate a large number of small requests for heap memory, with the +// intention that they are not individually deallocated, but rather +// collectively deallocated at one time. +// +// This simultaneously +// +// * Makes each individual allocation much more efficient; the +// typical allocation is trivial. +// * Completely avoids the cost of doing individual deallocation. +// * Saves the trouble of tracking down and plugging a large class of leaks. +// +// Individual classes can use this allocator by supplying their own +// new and delete methods. +// +// STL containers can use this allocator by using the pool_allocator +// class as the allocator (second) template argument. +// + +#include +#include +#include + +// If we are using guard blocks, we must track each indivual +// allocation. If we aren't using guard blocks, these +// never get instantiated, so won't have any impact. +// + +class TAllocation { +public: + TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) : + size(size), mem(mem), prevAlloc(prev) { + // Allocations are bracketed: + // [allocationHeader][initialGuardBlock][userData][finalGuardBlock] + // This would be cleaner with if (guardBlockSize)..., but that + // makes the compiler print warnings about 0 length memsets, + // even with the if() protecting them. +#ifdef GUARD_BLOCKS + memset(preGuard(), guardBlockBeginVal, guardBlockSize); + memset(data(), userDataFill, size); + memset(postGuard(), guardBlockEndVal, guardBlockSize); +#endif + } + + void check() const { + checkGuardBlock(preGuard(), guardBlockBeginVal, "before"); + checkGuardBlock(postGuard(), guardBlockEndVal, "after"); + } + + void checkAllocList() const; + + // Return total size needed to accomodate user buffer of 'size', + // plus our tracking data. + inline static size_t allocationSize(size_t size) { + return size + 2 * guardBlockSize + headerSize(); + } + + // Offset from surrounding buffer to get to user data buffer. + inline static unsigned char* offsetAllocation(unsigned char* m) { + return m + guardBlockSize + headerSize(); + } + +private: + void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const; + + // Find offsets to pre and post guard blocks, and user data buffer + unsigned char* preGuard() const { return mem + headerSize(); } + unsigned char* data() const { return preGuard() + guardBlockSize; } + unsigned char* postGuard() const { return data() + size; } + + size_t size; // size of the user data area + unsigned char* mem; // beginning of our allocation (pts to header) + TAllocation* prevAlloc; // prior allocation in the chain + + // Support MSVC++ 6.0 + const static unsigned char guardBlockBeginVal; + const static unsigned char guardBlockEndVal; + const static unsigned char userDataFill; + + const static size_t guardBlockSize; +#ifdef GUARD_BLOCKS + inline static size_t headerSize() { return sizeof(TAllocation); } +#else + inline static size_t headerSize() { return 0; } +#endif +}; + +// +// There are several stacks. One is to track the pushing and popping +// of the user, and not yet implemented. The others are simply a +// repositories of free pages or used pages. +// +// Page stacks are linked together with a simple header at the beginning +// of each allocation obtained from the underlying OS. Multi-page allocations +// are returned to the OS. Individual page allocations are kept for future +// re-use. +// +// The "page size" used is not, nor must it match, the underlying OS +// page size. But, having it be about that size or equal to a set of +// pages is likely most optimal. +// +class TPoolAllocator { +public: + TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16); + + // + // Don't call the destructor just to free up the memory, call pop() + // + ~TPoolAllocator(); + + // + // Call push() to establish a new place to pop memory too. Does not + // have to be called to get things started. + // + void push(); + + // + // Call pop() to free all memory allocated since the last call to push(), + // or if no last call to push, frees all memory since first allocation. + // + void pop(); + + // + // Call popAll() to free all memory allocated. + // + void popAll(); + + // + // Call allocate() to actually acquire memory. Returns 0 if no memory + // available, otherwise a properly aligned pointer to 'numBytes' of memory. + // + void* allocate(size_t numBytes); + + // + // There is no deallocate. The point of this class is that + // deallocation can be skipped by the user of it, as the model + // of use is to simultaneously deallocate everything at once + // by calling pop(), and to not have to solve memory leak problems. + // + +protected: + friend struct tHeader; + + struct tHeader { + tHeader(tHeader* nextPage, size_t pageCount) : + nextPage(nextPage), + pageCount(pageCount) +#ifdef GUARD_BLOCKS + , lastAllocation(0) +#endif + { } + + ~tHeader() { +#ifdef GUARD_BLOCKS + if (lastAllocation) + lastAllocation->checkAllocList(); +#endif + } + + tHeader* nextPage; + size_t pageCount; +#ifdef GUARD_BLOCKS + TAllocation* lastAllocation; +#endif + }; + + struct tAllocState { + size_t offset; + tHeader* page; + }; + typedef std::vector tAllocStack; + + // Track allocations if and only if we're using guard blocks + void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) { +#ifdef GUARD_BLOCKS + new(memory) TAllocation(numBytes, memory, block->lastAllocation); + block->lastAllocation = reinterpret_cast(memory); +#endif + // This is optimized entirely away if GUARD_BLOCKS is not defined. + return TAllocation::offsetAllocation(memory); + } + + size_t pageSize; // granularity of allocation from the OS + size_t alignment; // all returned allocations will be aligned at + // this granularity, which will be a power of 2 + size_t alignmentMask; + size_t headerSkip; // amount of memory to skip to make room for the + // header (basically, size of header, rounded + // up to make it aligned + size_t currentPageOffset; // next offset in top of inUseList to allocate from + tHeader* freeList; // list of popped memory + tHeader* inUseList; // list of all memory currently being used + tAllocStack stack; // stack of where to allocate from, to partition pool + + int numCalls; // just an interesting statistic + size_t totalBytes; // just an interesting statistic +private: + TPoolAllocator& operator=(const TPoolAllocator&); // dont allow assignment operator + TPoolAllocator(const TPoolAllocator&); // dont allow default copy constructor +}; + + +// +// There could potentially be many pools with pops happening at +// different times. But a simple use is to have a global pop +// with everyone using the same global allocator. +// +extern TPoolAllocator* GetGlobalPoolAllocator(); +extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator); + +// +// This STL compatible allocator is intended to be used as the allocator +// parameter to templatized STL containers, like vector and map. +// +// It will use the pools for allocation, and not +// do any deallocation, but will still do destruction. +// +template +class pool_allocator { +public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + + template + struct rebind { + typedef pool_allocator other; + }; + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + + pool_allocator() : allocator(GetGlobalPoolAllocator()) { } + pool_allocator(TPoolAllocator& a) : allocator(&a) { } + pool_allocator(const pool_allocator& p) : allocator(p.allocator) { } + + template + pool_allocator& operator=(const pool_allocator& p) { + allocator = p.allocator; + return *this; + } + + template + pool_allocator(const pool_allocator& p) : allocator(&p.getAllocator()) { } + +#if defined(__SUNPRO_CC) && !defined(_RWSTD_ALLOCATOR) + // libCStd on some platforms have a different allocate/deallocate interface. + // Caller pre-bakes sizeof(T) into 'n' which is the number of bytes to be + // allocated, not the number of elements. + void* allocate(size_type n) { + return getAllocator().allocate(n); + } + void* allocate(size_type n, const void*) { + return getAllocator().allocate(n); + } + void deallocate(void*, size_type) {} +#else + pointer allocate(size_type n) { + return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); + } + pointer allocate(size_type n, const void*) { + return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); + } + void deallocate(pointer, size_type) {} +#endif // _RWSTD_ALLOCATOR + + void construct(pointer p, const T& val) { new ((void *)p) T(val); } + void destroy(pointer p) { p->T::~T(); } + + bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); } + bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); } + + size_type max_size() const { return static_cast(-1) / sizeof(T); } + size_type max_size(int size) const { return static_cast(-1) / size; } + + void setAllocator(TPoolAllocator* a) { allocator = a; } + TPoolAllocator& getAllocator() const { return *allocator; } + +protected: + TPoolAllocator* allocator; +}; + +#endif // _POOLALLOC_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/Pragma.h b/src/3rdparty/angle/src/compiler/translator/Pragma.h new file mode 100644 index 0000000000..2f744123b8 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/Pragma.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PRAGMA_H_ +#define COMPILER_PRAGMA_H_ + +struct TPragma { + // By default optimization is turned on and debug is turned off. + TPragma() : optimize(true), debug(false) { } + TPragma(bool o, bool d) : optimize(o), debug(d) { } + + bool optimize; + bool debug; +}; + +#endif // COMPILER_PRAGMA_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp new file mode 100644 index 0000000000..1ba087e176 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp @@ -0,0 +1,58 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/intermediate.h" + +class TAliveTraverser : public TIntermTraverser { +public: + TAliveTraverser(TQualifier q) : TIntermTraverser(true, false, false, true), found(false), qualifier(q) + { + } + + bool wasFound() { return found; } + +protected: + bool found; + TQualifier qualifier; + + void visitSymbol(TIntermSymbol*); + bool visitSelection(Visit, TIntermSelection*); +}; + +// +// Report whether or not a variable of the given qualifier type +// is guaranteed written. Not always possible to determine if +// it is written conditionally. +// +// ?? It does not do this well yet, this is just a place holder +// that simply determines if it was reference at all, anywhere. +// +bool QualifierWritten(TIntermNode* node, TQualifier qualifier) +{ + TAliveTraverser it(qualifier); + + if (node) + node->traverse(&it); + + return it.wasFound(); +} + +void TAliveTraverser::visitSymbol(TIntermSymbol* node) +{ + // + // If it's what we're looking for, record it. + // + if (node->getQualifier() == qualifier) + found = true; +} + +bool TAliveTraverser::visitSelection(Visit preVisit, TIntermSelection* node) +{ + if (wasFound()) + return false; + + return true; +} diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h new file mode 100644 index 0000000000..872a06f721 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h @@ -0,0 +1,7 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +bool QualifierWritten(TIntermNode* root, TQualifier); diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp new file mode 100644 index 0000000000..92e5dbbfe1 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp @@ -0,0 +1,77 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/intermediate.h" +#include "compiler/translator/RemoveTree.h" + +// +// Code to recursively delete the intermediate tree. +// + +class RemoveTree : public TIntermTraverser +{ +public: + RemoveTree() : TIntermTraverser(false, false, true) + { + } + +protected: + void visitSymbol(TIntermSymbol*); + void visitConstantUnion(TIntermConstantUnion*); + bool visitBinary(Visit visit, TIntermBinary*); + bool visitUnary(Visit visit, TIntermUnary*); + bool visitSelection(Visit visit, TIntermSelection*); + bool visitAggregate(Visit visit, TIntermAggregate*); +}; + +void RemoveTree::visitSymbol(TIntermSymbol* node) +{ + delete node; +} + +bool RemoveTree::visitBinary(Visit visit, TIntermBinary* node) +{ + delete node; + + return true; +} + +bool RemoveTree::visitUnary(Visit visit, TIntermUnary* node) +{ + delete node; + + return true; +} + +bool RemoveTree::visitAggregate(Visit visit, TIntermAggregate* node) +{ + delete node; + + return true; +} + +bool RemoveTree::visitSelection(Visit visit, TIntermSelection* node) +{ + delete node; + + return true; +} + +void RemoveTree::visitConstantUnion(TIntermConstantUnion* node) +{ + delete node; +} + +// +// Entry point. +// +void RemoveAllTreeNodes(TIntermNode* root) +{ + RemoveTree it; + + root->traverse(&it); +} + diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveTree.h b/src/3rdparty/angle/src/compiler/translator/RemoveTree.h new file mode 100644 index 0000000000..97a821679c --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/RemoveTree.h @@ -0,0 +1,7 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +void RemoveAllTreeNodes(TIntermNode*); diff --git a/src/3rdparty/angle/src/compiler/translator/RenameFunction.h b/src/3rdparty/angle/src/compiler/translator/RenameFunction.h new file mode 100644 index 0000000000..1f7fb16c45 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/RenameFunction.h @@ -0,0 +1,36 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_RENAME_FUNCTION +#define COMPILER_RENAME_FUNCTION + +#include "compiler/translator/intermediate.h" + +// +// Renames a function, including its declaration and any calls to it. +// +class RenameFunction : public TIntermTraverser +{ +public: + RenameFunction(const TString& oldFunctionName, const TString& newFunctionName) + : TIntermTraverser(true, false, false) + , mOldFunctionName(oldFunctionName) + , mNewFunctionName(newFunctionName) {} + + virtual bool visitAggregate(Visit visit, TIntermAggregate* node) + { + TOperator op = node->getOp(); + if ((op == EOpFunction || op == EOpFunctionCall) && node->getName() == mOldFunctionName) + node->setName(mNewFunctionName); + return true; + } + +private: + const TString mOldFunctionName; + const TString mNewFunctionName; +}; + +#endif // COMPILER_RENAME_FUNCTION diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp new file mode 100644 index 0000000000..48e87cd57a --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp @@ -0,0 +1,98 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteElseBlocks.cpp: Implementation for tree transform to change +// all if-else blocks to if-if blocks. +// + +#include "compiler/translator/RewriteElseBlocks.h" +#include "compiler/translator/NodeSearch.h" +#include "compiler/translator/SymbolTable.h" + +namespace sh +{ + +TIntermSymbol *MakeNewTemporary(const TString &name, TBasicType type) +{ + TType variableType(type, EbpHigh, EvqInternal); + return new TIntermSymbol(-1, name, variableType); +} + +TIntermBinary *MakeNewBinary(TOperator op, TIntermTyped *left, TIntermTyped *right, const TType &resultType) +{ + TIntermBinary *binary = new TIntermBinary(op); + binary->setLeft(left); + binary->setRight(right); + binary->setType(resultType); + return binary; +} + +TIntermUnary *MakeNewUnary(TOperator op, TIntermTyped *operand) +{ + TIntermUnary *unary = new TIntermUnary(op, operand->getType()); + unary->setOperand(operand); + return unary; +} + +bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node) +{ + switch (node->getOp()) + { + case EOpSequence: + { + for (size_t statementIndex = 0; statementIndex != node->getSequence().size(); statementIndex++) + { + TIntermNode *statement = node->getSequence()[statementIndex]; + TIntermSelection *selection = statement->getAsSelectionNode(); + if (selection && selection->getFalseBlock() != NULL) + { + node->getSequence()[statementIndex] = rewriteSelection(selection); + delete selection; + } + } + } + break; + + default: break; + } + + return true; +} + +TIntermNode *ElseBlockRewriter::rewriteSelection(TIntermSelection *selection) +{ + ASSERT(selection->getFalseBlock() != NULL); + + TString temporaryName = "cond_" + str(mTemporaryIndex++); + TIntermTyped *typedCondition = selection->getCondition()->getAsTyped(); + TType resultType(EbtBool, EbpUndefined); + TIntermSymbol *conditionSymbolA = MakeNewTemporary(temporaryName, EbtBool); + TIntermSymbol *conditionSymbolB = MakeNewTemporary(temporaryName, EbtBool); + TIntermSymbol *conditionSymbolC = MakeNewTemporary(temporaryName, EbtBool); + TIntermBinary *storeCondition = MakeNewBinary(EOpInitialize, conditionSymbolA, + typedCondition, resultType); + TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolB); + TIntermSelection *falseBlock = new TIntermSelection(negatedCondition, + selection->getFalseBlock(), NULL); + TIntermSelection *newIfElse = new TIntermSelection(conditionSymbolC, + selection->getTrueBlock(), falseBlock); + + TIntermAggregate *declaration = new TIntermAggregate(EOpDeclaration); + declaration->getSequence().push_back(storeCondition); + + TIntermAggregate *block = new TIntermAggregate(EOpSequence); + block->getSequence().push_back(declaration); + block->getSequence().push_back(newIfElse); + + return block; +} + +void RewriteElseBlocks(TIntermNode *node) +{ + ElseBlockRewriter rewriter; + node->traverse(&rewriter); +} + +} diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h new file mode 100644 index 0000000000..10221335ce --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteElseBlocks.h: Prototype for tree transform to change +// all if-else blocks to if-if blocks. +// + +#ifndef COMPILER_REWRITE_ELSE_BLOCKS_H_ +#define COMPILER_REWRITE_ELSE_BLOCKS_H_ + +#include "compiler/translator/intermediate.h" + +namespace sh +{ + +class ElseBlockRewriter : public TIntermTraverser +{ + public: + ElseBlockRewriter() + : TIntermTraverser(false, false, true, false) + , mTemporaryIndex(0) + {} + + protected: + bool visitAggregate(Visit visit, TIntermAggregate *aggregate); + + private: + int mTemporaryIndex; + + TIntermNode *rewriteSelection(TIntermSelection *selection); +}; + +void RewriteElseBlocks(TIntermNode *node); + +} + +#endif // COMPILER_REWRITE_ELSE_BLOCKS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp new file mode 100644 index 0000000000..f78c84e370 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/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/translator/SearchSymbol.h" + +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/OutputHLSL.h" + +namespace sh +{ +SearchSymbol::SearchSymbol(const TString &symbol) : mSymbol(symbol) +{ + match = false; +} + +void SearchSymbol::traverse(TIntermNode *node) +{ + node->traverse(this); +} + +void SearchSymbol::visitSymbol(TIntermSymbol *symbolNode) +{ + if (symbolNode->getSymbol() == mSymbol) + { + match = true; + } +} + +bool SearchSymbol::foundMatch() const +{ + return match; +} +} diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h new file mode 100644 index 0000000000..8ddd3cb1ac --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/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/translator/intermediate.h" +#include "compiler/translator/ParseContext.h" + +namespace sh +{ +class SearchSymbol : public TIntermTraverser +{ + public: + SearchSymbol(const TString &symbol); + + void traverse(TIntermNode *node); + void visitSymbol(TIntermSymbol *symbolNode); + + bool foundMatch() const; + + protected: + const TString &mSymbol; + bool match; +}; +} + +#endif // COMPILER_SEARCHSYMBOL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ShHandle.h b/src/3rdparty/angle/src/compiler/translator/ShHandle.h new file mode 100644 index 0000000000..54ae27852d --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ShHandle.h @@ -0,0 +1,179 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _SHHANDLE_INCLUDED_ +#define _SHHANDLE_INCLUDED_ + +// +// Machine independent part of the compiler private objects +// sent as ShHandle to the driver. +// +// This should not be included by driver code. +// + +#include "GLSLANG/ShaderLang.h" + +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/ExtensionBehavior.h" +#include "compiler/translator/HashNames.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/VariableInfo.h" +#include "third_party/compiler/ArrayBoundsClamper.h" + +class LongNameMap; +class TCompiler; +class TDependencyGraph; +class TranslatorHLSL; + +// +// Helper function to identify specs that are based on the WebGL spec, +// like the CSS Shaders spec. +// +bool isWebGLBasedSpec(ShShaderSpec spec); + +// +// The base class used to back handles returned to the driver. +// +class TShHandleBase { +public: + TShHandleBase(); + virtual ~TShHandleBase(); + virtual TCompiler* getAsCompiler() { return 0; } + virtual TranslatorHLSL* getAsTranslatorHLSL() { return 0; } + +protected: + // Memory allocator. Allocates and tracks memory required by the compiler. + // Deallocates all memory when compiler is destructed. + TPoolAllocator allocator; +}; + +// +// The base class for the machine dependent compiler to derive from +// for managing object code from the compile. +// +class TCompiler : public TShHandleBase { +public: + TCompiler(ShShaderType type, ShShaderSpec spec); + virtual ~TCompiler(); + virtual TCompiler* getAsCompiler() { return this; } + + bool Init(const ShBuiltInResources& resources); + bool compile(const char* const shaderStrings[], + size_t numStrings, + int compileOptions); + + // Get results of the last compilation. + TInfoSink& getInfoSink() { return infoSink; } + const TVariableInfoList& getAttribs() const { return attribs; } + const TVariableInfoList& getUniforms() const { return uniforms; } + const TVariableInfoList& getVaryings() const { return varyings; } + int getMappedNameMaxLength() const; + + ShHashFunction64 getHashFunction() const { return hashFunction; } + NameMap& getNameMap() { return nameMap; } + TSymbolTable& getSymbolTable() { return symbolTable; } + +protected: + ShShaderType getShaderType() const { return shaderType; } + ShShaderSpec getShaderSpec() const { return shaderSpec; } + // Initialize symbol-table with built-in symbols. + bool InitBuiltInSymbolTable(const ShBuiltInResources& resources); + // Clears the results from the previous compilation. + void clearResults(); + // Return true if function recursion is detected or call depth exceeded. + bool detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth); + // Rewrites a shader's intermediate tree according to the CSS Shaders spec. + void rewriteCSSShader(TIntermNode* root); + // Returns true if the given shader does not exceed the minimum + // functionality mandated in GLSL 1.0 spec Appendix A. + bool validateLimitations(TIntermNode* root); + // Collect info for all attribs, uniforms, varyings. + void collectVariables(TIntermNode* root); + // Map long variable names into shorter ones. + void mapLongVariableNames(TIntermNode* root); + // Translate to object code. + virtual void translate(TIntermNode* root) = 0; + // Returns true if, after applying the packing rules in the GLSL 1.017 spec + // Appendix A, section 7, the shader does not use too many uniforms. + bool enforcePackingRestrictions(); + // Insert statements to initialize varyings without static use in the beginning + // of main(). It is to work around a Mac driver where such varyings in a vertex + // shader may be optimized out incorrectly at compile time, causing a link failure. + // This function should only be applied to vertex shaders. + void initializeVaryingsWithoutStaticUse(TIntermNode* root); + // Insert gl_Position = vec4(0,0,0,0) to the beginning of main(). + // It is to work around a Linux driver bug where missing this causes compile failure + // while spec says it is allowed. + // This function should only be applied to vertex shaders. + void initializeGLPosition(TIntermNode* root); + // Returns true if the shader passes the restrictions that aim to prevent timing attacks. + bool enforceTimingRestrictions(TIntermNode* root, bool outputGraph); + // Returns true if the shader does not use samplers. + bool enforceVertexShaderTimingRestrictions(TIntermNode* root); + // Returns true if the shader does not use sampler dependent values to affect control + // flow or in operations whose time can depend on the input values. + bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph); + // Return true if the maximum expression complexity below the limit. + bool limitExpressionComplexity(TIntermNode* root); + // Get built-in extensions with default behavior. + const TExtensionBehavior& getExtensionBehavior() const; + // Get the resources set by InitBuiltInSymbolTable + const ShBuiltInResources& getResources() const; + + const ArrayBoundsClamper& getArrayBoundsClamper() const; + ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const; + const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const; + +private: + ShShaderType shaderType; + ShShaderSpec shaderSpec; + + int maxUniformVectors; + int maxExpressionComplexity; + int maxCallStackDepth; + + ShBuiltInResources compileResources; + + // Built-in symbol table for the given language, spec, and resources. + // It is preserved from compile-to-compile. + TSymbolTable symbolTable; + // Built-in extensions with default behavior. + TExtensionBehavior extensionBehavior; + bool fragmentPrecisionHigh; + + ArrayBoundsClamper arrayBoundsClamper; + ShArrayIndexClampingStrategy clampingStrategy; + BuiltInFunctionEmulator builtInFunctionEmulator; + + // Results of compilation. + TInfoSink infoSink; // Output sink. + TVariableInfoList attribs; // Active attributes in the compiled shader. + TVariableInfoList uniforms; // Active uniforms in the compiled shader. + TVariableInfoList varyings; // Varyings in the compiled shader. + + // Cached copy of the ref-counted singleton. + LongNameMap* longNameMap; + + // name hashing. + ShHashFunction64 hashFunction; + NameMap nameMap; +}; + +// +// This is the interface between the machine independent code +// and the machine dependent code. +// +// The machine dependent code should derive from the classes +// above. Then Construct*() and Delete*() will create and +// destroy the machine dependent objects, which contain the +// above machine independent information. +// +TCompiler* ConstructCompiler( + ShShaderType type, ShShaderSpec spec, ShShaderOutput output); +void DeleteCompiler(TCompiler*); + +#endif // _SHHANDLE_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp new file mode 100644 index 0000000000..608237860c --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp @@ -0,0 +1,390 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// +// Implement the top-level of interface to the compiler, +// as defined in ShaderLang.h +// + +#include "GLSLANG/ShaderLang.h" + +#include "compiler/translator/InitializeDll.h" +#include "compiler/preprocessor/length_limits.h" +#include "compiler/translator/ShHandle.h" +#include "compiler/translator/TranslatorHLSL.h" +#include "compiler/translator/VariablePacker.h" + +// +// This is the platform independent interface between an OGL driver +// and the shading language compiler. +// + +static bool checkVariableMaxLengths(const ShHandle handle, + size_t expectedValue) +{ + size_t activeUniformLimit = 0; + ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit); + size_t activeAttribLimit = 0; + ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit); + size_t varyingLimit = 0; + ShGetInfo(handle, SH_VARYING_MAX_LENGTH, &varyingLimit); + return (expectedValue == activeUniformLimit && + expectedValue == activeAttribLimit && + expectedValue == varyingLimit); +} + +static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue) +{ + size_t mappedNameMaxLength = 0; + ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength); + return (expectedValue == mappedNameMaxLength); +} + +// +// Driver must call this first, once, before doing any other compiler operations. +// Subsequent calls to this function are no-op. +// +int ShInitialize() +{ + static const bool kInitialized = InitProcess(); + return kInitialized ? 1 : 0; +} + +// +// Cleanup symbol tables +// +int ShFinalize() +{ + DetachProcess(); + return 1; +} + +// +// Initialize built-in resources with minimum expected values. +// +void ShInitBuiltInResources(ShBuiltInResources* resources) +{ + // Constants. + resources->MaxVertexAttribs = 8; + resources->MaxVertexUniformVectors = 128; + resources->MaxVaryingVectors = 8; + resources->MaxVertexTextureImageUnits = 0; + resources->MaxCombinedTextureImageUnits = 8; + resources->MaxTextureImageUnits = 8; + resources->MaxFragmentUniformVectors = 16; + resources->MaxDrawBuffers = 1; + + // Extensions. + resources->OES_standard_derivatives = 0; + resources->OES_EGL_image_external = 0; + resources->ARB_texture_rectangle = 0; + resources->EXT_draw_buffers = 0; + resources->EXT_frag_depth = 0; + + // Disable highp precision in fragment shader by default. + resources->FragmentPrecisionHigh = 0; + + // Disable name hashing by default. + resources->HashFunction = NULL; + + resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC; + + resources->MaxExpressionComplexity = 256; + resources->MaxCallStackDepth = 256; +} + +// +// Driver calls these to create and destroy compiler objects. +// +ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, + ShShaderOutput output, + const ShBuiltInResources* resources) +{ + TShHandleBase* base = static_cast(ConstructCompiler(type, spec, output)); + TCompiler* compiler = base->getAsCompiler(); + if (compiler == 0) + return 0; + + // Generate built-in symbol table. + if (!compiler->Init(*resources)) { + ShDestruct(base); + return 0; + } + + return reinterpret_cast(base); +} + +void ShDestruct(ShHandle handle) +{ + if (handle == 0) + return; + + TShHandleBase* base = static_cast(handle); + + if (base->getAsCompiler()) + DeleteCompiler(base->getAsCompiler()); +} + +// +// Do an actual compile on the given strings. The result is left +// in the given compile object. +// +// Return: The return value of ShCompile is really boolean, indicating +// success or failure. +// +int ShCompile( + const ShHandle handle, + const char* const shaderStrings[], + size_t numStrings, + int compileOptions) +{ + if (handle == 0) + return 0; + + TShHandleBase* base = reinterpret_cast(handle); + TCompiler* compiler = base->getAsCompiler(); + if (compiler == 0) + return 0; + + bool success = compiler->compile(shaderStrings, numStrings, compileOptions); + return success ? 1 : 0; +} + +void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params) +{ + if (!handle || !params) + return; + + TShHandleBase* base = static_cast(handle); + TCompiler* compiler = base->getAsCompiler(); + if (!compiler) return; + + switch(pname) + { + case SH_INFO_LOG_LENGTH: + *params = compiler->getInfoSink().info.size() + 1; + break; + case SH_OBJECT_CODE_LENGTH: + *params = compiler->getInfoSink().obj.size() + 1; + break; + case SH_ACTIVE_UNIFORMS: + *params = compiler->getUniforms().size(); + break; + case SH_ACTIVE_UNIFORM_MAX_LENGTH: + *params = 1 + MAX_SYMBOL_NAME_LEN; + break; + case SH_ACTIVE_ATTRIBUTES: + *params = compiler->getAttribs().size(); + break; + case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: + *params = 1 + MAX_SYMBOL_NAME_LEN; + break; + case SH_VARYINGS: + *params = compiler->getVaryings().size(); + break; + case SH_VARYING_MAX_LENGTH: + *params = 1 + MAX_SYMBOL_NAME_LEN; + break; + case SH_MAPPED_NAME_MAX_LENGTH: + // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to + // handle array and struct dereferences. + *params = 1 + MAX_SYMBOL_NAME_LEN; + break; + case SH_NAME_MAX_LENGTH: + *params = 1 + MAX_SYMBOL_NAME_LEN; + break; + case SH_HASHED_NAME_MAX_LENGTH: + if (compiler->getHashFunction() == NULL) { + *params = 0; + } else { + // 64 bits hashing output requires 16 bytes for hex + // representation. + const char HashedNamePrefix[] = HASHED_NAME_PREFIX; + *params = 16 + sizeof(HashedNamePrefix); + } + break; + case SH_HASHED_NAMES_COUNT: + *params = compiler->getNameMap().size(); + break; + default: UNREACHABLE(); + } +} + +// +// Return any compiler log of messages for the application. +// +void ShGetInfoLog(const ShHandle handle, char* infoLog) +{ + if (!handle || !infoLog) + return; + + TShHandleBase* base = static_cast(handle); + TCompiler* compiler = base->getAsCompiler(); + if (!compiler) return; + + TInfoSink& infoSink = compiler->getInfoSink(); + strcpy(infoLog, infoSink.info.c_str()); +} + +// +// Return any object code. +// +void ShGetObjectCode(const ShHandle handle, char* objCode) +{ + if (!handle || !objCode) + return; + + TShHandleBase* base = static_cast(handle); + TCompiler* compiler = base->getAsCompiler(); + if (!compiler) return; + + TInfoSink& infoSink = compiler->getInfoSink(); + strcpy(objCode, infoSink.obj.c_str()); +} + +void ShGetVariableInfo(const ShHandle handle, + ShShaderInfo varType, + int index, + size_t* length, + int* size, + ShDataType* type, + ShPrecisionType* precision, + int* staticUse, + char* name, + char* mappedName) +{ + if (!handle || !size || !type || !precision || !staticUse || !name) + return; + ASSERT((varType == SH_ACTIVE_ATTRIBUTES) || + (varType == SH_ACTIVE_UNIFORMS) || + (varType == SH_VARYINGS)); + + TShHandleBase* base = reinterpret_cast(handle); + TCompiler* compiler = base->getAsCompiler(); + if (compiler == 0) + return; + + const TVariableInfoList& varList = + varType == SH_ACTIVE_ATTRIBUTES ? compiler->getAttribs() : + (varType == SH_ACTIVE_UNIFORMS ? compiler->getUniforms() : + compiler->getVaryings()); + 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; + switch (varInfo.precision) { + case EbpLow: + *precision = SH_PRECISION_LOWP; + break; + case EbpMedium: + *precision = SH_PRECISION_MEDIUMP; + break; + case EbpHigh: + *precision = SH_PRECISION_HIGHP; + break; + default: + // Some types does not support precision, for example, boolean. + *precision = SH_PRECISION_UNDEFINED; + break; + } + *staticUse = varInfo.staticUse ? 1 : 0; + + // This size must match that queried by + // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH + // in ShGetInfo, below. + size_t variableLength = 1 + MAX_SYMBOL_NAME_LEN; + ASSERT(checkVariableMaxLengths(handle, variableLength)); + strncpy(name, varInfo.name.c_str(), variableLength); + name[variableLength - 1] = 0; + if (mappedName) { + // This size must match that queried by + // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. + size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN; + ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength)); + strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength); + mappedName[maxMappedNameLength - 1] = 0; + } +} + +void ShGetNameHashingEntry(const ShHandle handle, + int index, + char* name, + char* hashedName) +{ + if (!handle || !name || !hashedName || index < 0) + return; + + TShHandleBase* base = static_cast(handle); + TCompiler* compiler = base->getAsCompiler(); + if (!compiler) return; + + const NameMap& nameMap = compiler->getNameMap(); + if (index >= static_cast(nameMap.size())) + return; + + NameMap::const_iterator it = nameMap.begin(); + for (int i = 0; i < index; ++i) + ++it; + + size_t len = it->first.length() + 1; + size_t max_len = 0; + ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len); + if (len > max_len) { + ASSERT(false); + len = max_len; + } + strncpy(name, it->first.c_str(), len); + // To be on the safe side in case the source is longer than expected. + name[len - 1] = '\0'; + + len = it->second.length() + 1; + max_len = 0; + ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len); + if (len > max_len) { + ASSERT(false); + len = max_len; + } + strncpy(hashedName, it->second.c_str(), len); + // To be on the safe side in case the source is longer than expected. + hashedName[len - 1] = '\0'; +} + +void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params) +{ + if (!handle || !params) + return; + + TShHandleBase* base = static_cast(handle); + TranslatorHLSL* translator = base->getAsTranslatorHLSL(); + if (!translator) return; + + switch(pname) + { + case SH_ACTIVE_UNIFORMS_ARRAY: + *params = (void*)&translator->getUniforms(); + break; + default: UNREACHABLE(); + } +} + +int ShCheckVariablesWithinPackingLimits( + int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize) +{ + if (varInfoArraySize == 0) + return 1; + ASSERT(varInfoArray); + TVariableInfoList variables; + for (size_t ii = 0; ii < varInfoArraySize; ++ii) + { + TVariableInfo var(varInfoArray[ii].type, varInfoArray[ii].size); + variables.push_back(var); + } + VariablePacker packer; + return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0; +} diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp new file mode 100644 index 0000000000..d04fe5d355 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp @@ -0,0 +1,216 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// +// Symbol table for parsing. Most functionaliy and main ideas +// are documented in the header file. +// + +#if defined(_MSC_VER) +#pragma warning(disable: 4718) +#endif + +#include "compiler/translator/SymbolTable.h" + +#include +#include +#include + +TType::TType(const TPublicType &p) : + type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), structure(0) +{ + if (p.userDef) + structure = p.userDef->getStruct(); +} + +// +// Recursively generate mangled names. +// +TString TType::buildMangledName() const +{ + TString mangledName; + if (isMatrix()) + mangledName += 'm'; + else if (isVector()) + mangledName += 'v'; + + switch (type) { + case EbtFloat: mangledName += 'f'; break; + case EbtInt: mangledName += 'i'; break; + case EbtBool: mangledName += 'b'; break; + case EbtSampler2D: mangledName += "s2"; break; + case EbtSamplerCube: mangledName += "sC"; break; + case EbtStruct: mangledName += structure->mangledName(); break; + default: break; + } + + mangledName += static_cast('0' + getNominalSize()); + if (isArray()) { + char buf[20]; + snprintf(buf, sizeof(buf), "%d", arraySize); + mangledName += '['; + mangledName += buf; + mangledName += ']'; + } + return mangledName; +} + +size_t TType::getObjectSize() const +{ + size_t totalSize = 0; + + if (getBasicType() == EbtStruct) + totalSize = structure->objectSize(); + else if (matrix) + totalSize = size * size; + else + totalSize = size; + + if (isArray()) { + size_t arraySize = getArraySize(); + if (arraySize > INT_MAX / totalSize) + totalSize = INT_MAX; + else + totalSize *= arraySize; + } + + return totalSize; +} + +bool TStructure::containsArrays() const +{ + for (size_t i = 0; i < mFields->size(); ++i) { + const TType* fieldType = (*mFields)[i]->type(); + if (fieldType->isArray() || fieldType->isStructureContainingArrays()) + return true; + } + return false; +} + +TString TStructure::buildMangledName() const +{ + TString mangledName("struct-"); + mangledName += *mName; + for (size_t i = 0; i < mFields->size(); ++i) { + mangledName += '-'; + mangledName += (*mFields)[i]->type()->getMangledName(); + } + return mangledName; +} + +size_t TStructure::calculateObjectSize() const +{ + size_t size = 0; + for (size_t i = 0; i < mFields->size(); ++i) { + size_t fieldSize = (*mFields)[i]->type()->getObjectSize(); + if (fieldSize > INT_MAX - size) + size = INT_MAX; + else + size += fieldSize; + } + return size; +} + +int TStructure::calculateDeepestNesting() const +{ + int maxNesting = 0; + for (size_t i = 0; i < mFields->size(); ++i) { + maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting()); + } + return 1 + maxNesting; +} + +// +// Dump functions. +// + +void TVariable::dump(TInfoSink& infoSink) const +{ + infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getPrecisionString() << " " << type.getBasicString(); + if (type.isArray()) { + infoSink.debug << "[0]"; + } + infoSink.debug << "\n"; +} + +void TFunction::dump(TInfoSink &infoSink) const +{ + infoSink.debug << getName().c_str() << ": " << returnType.getBasicString() << " " << getMangledName().c_str() << "\n"; +} + +void TSymbolTableLevel::dump(TInfoSink &infoSink) const +{ + tLevel::const_iterator it; + for (it = level.begin(); it != level.end(); ++it) + (*it).second->dump(infoSink); +} + +void TSymbolTable::dump(TInfoSink &infoSink) const +{ + for (int level = currentLevel(); level >= 0; --level) { + infoSink.debug << "LEVEL " << level << "\n"; + table[level]->dump(infoSink); + } +} + +// +// Functions have buried pointers to delete. +// +TFunction::~TFunction() +{ + for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i) + delete (*i).type; +} + +// +// Symbol table levels are a map of pointers to symbols that have to be deleted. +// +TSymbolTableLevel::~TSymbolTableLevel() +{ + for (tLevel::iterator it = level.begin(); it != level.end(); ++it) + delete (*it).second; +} + +// +// Change all function entries in the table with the non-mangled name +// to be related to the provided built-in operation. This is a low +// performance operation, and only intended for symbol tables that +// live across a large number of compiles. +// +void TSymbolTableLevel::relateToOperator(const char* name, TOperator op) +{ + tLevel::iterator it; + for (it = level.begin(); it != level.end(); ++it) { + if ((*it).second->isFunction()) { + TFunction* function = static_cast((*it).second); + if (function->getName() == name) + function->relateToOperator(op); + } + } +} + +// +// Change all function entries in the table with the non-mangled name +// to be related to the provided built-in extension. This is a low +// performance operation, and only intended for symbol tables that +// live across a large number of compiles. +// +void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext) +{ + for (tLevel::iterator it = level.begin(); it != level.end(); ++it) { + TSymbol* symbol = it->second; + if (symbol->getName() == name) + symbol->relateToExtension(ext); + } +} + +TSymbolTable::~TSymbolTable() +{ + for (size_t i = 0; i < table.size(); ++i) + delete table[i]; + for (size_t i = 0; i < precisionStack.size(); ++i) + delete precisionStack[i]; +} diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h new file mode 100644 index 0000000000..6c7211f2a9 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h @@ -0,0 +1,382 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _SYMBOL_TABLE_INCLUDED_ +#define _SYMBOL_TABLE_INCLUDED_ + +// +// Symbol table for parsing. Has these design characteristics: +// +// * Same symbol table can be used to compile many shaders, to preserve +// effort of creating and loading with the large numbers of built-in +// symbols. +// +// * Name mangling will be used to give each function a unique name +// so that symbol table lookups are never ambiguous. This allows +// a simpler symbol table structure. +// +// * Pushing and popping of scope, so symbol table will really be a stack +// of symbol tables. Searched from the top, with new inserts going into +// the top. +// +// * Constants: Compile time constant symbols will keep their values +// in the symbol table. The parser can substitute constants at parse +// time, including doing constant folding and constant propagation. +// +// * No temporaries: Temporaries made from operations (+, --, .xy, etc.) +// are tracked in the intermediate representation, not the symbol table. +// + +#include + +#include "common/angleutils.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/intermediate.h" + +// +// Symbol base class. (Can build functions or variables out of these...) +// +class TSymbol { +public: + POOL_ALLOCATOR_NEW_DELETE(); + TSymbol(const TString* n) : uniqueId(0), name(n) { } + virtual ~TSymbol() { /* don't delete name, it's from the pool */ } + + const TString& getName() const { return *name; } + virtual const TString& getMangledName() const { return getName(); } + virtual bool isFunction() const { return false; } + virtual bool isVariable() const { return false; } + void setUniqueId(int id) { uniqueId = id; } + int getUniqueId() const { return uniqueId; } + virtual void dump(TInfoSink &infoSink) const = 0; + void relateToExtension(const TString& ext) { extension = ext; } + const TString& getExtension() const { return extension; } + +private: + DISALLOW_COPY_AND_ASSIGN(TSymbol); + + int uniqueId; // For real comparing during code generation + const TString *name; + TString extension; +}; + +// +// Variable class, meaning a symbol that's not a function. +// +// There could be a separate class heirarchy for Constant variables; +// Only one of int, bool, or float, (or none) is correct for +// any particular use, but it's easy to do this way, and doesn't +// seem worth having separate classes, and "getConst" can't simply return +// different values for different types polymorphically, so this is +// just simple and pragmatic. +// +class TVariable : public TSymbol { +public: + TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0) { } + virtual ~TVariable() { } + virtual bool isVariable() const { return true; } + TType& getType() { return type; } + const TType& getType() const { return type; } + bool isUserType() const { return userType; } + void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); } + + virtual void dump(TInfoSink &infoSink) const; + + ConstantUnion* getConstPointer() + { + if (!unionArray) + unionArray = new ConstantUnion[type.getObjectSize()]; + + return unionArray; + } + + ConstantUnion* getConstPointer() const { return unionArray; } + + void shareConstPointer( ConstantUnion *constArray) + { + if (unionArray == constArray) + return; + + delete[] unionArray; + unionArray = constArray; + } + +private: + DISALLOW_COPY_AND_ASSIGN(TVariable); + + TType type; + bool userType; + // we are assuming that Pool Allocator will free the memory allocated to unionArray + // when this object is destroyed + ConstantUnion *unionArray; +}; + +// +// The function sub-class of symbols and the parser will need to +// share this definition of a function parameter. +// +struct TParameter { + TString *name; + TType* type; +}; + +// +// The function sub-class of a symbol. +// +class TFunction : public TSymbol { +public: + TFunction(TOperator o) : + TSymbol(0), + returnType(TType(EbtVoid, EbpUndefined)), + op(o), + defined(false) { } + TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) : + TSymbol(name), + returnType(retType), + mangledName(TFunction::mangleName(*name)), + op(tOp), + defined(false) { } + virtual ~TFunction(); + virtual bool isFunction() const { return true; } + + static TString mangleName(const TString& name) { return name + '('; } + static TString unmangleName(const TString& mangledName) + { + return TString(mangledName.c_str(), mangledName.find_first_of('(')); + } + + void addParameter(TParameter& p) + { + parameters.push_back(p); + mangledName = mangledName + p.type->getMangledName(); + } + + const TString& getMangledName() const { return mangledName; } + const TType& getReturnType() const { return returnType; } + + void relateToOperator(TOperator o) { op = o; } + TOperator getBuiltInOp() const { return op; } + + void setDefined() { defined = true; } + bool isDefined() { return defined; } + + size_t getParamCount() const { return parameters.size(); } + const TParameter& getParam(size_t i) const { return parameters[i]; } + + virtual void dump(TInfoSink &infoSink) const; + +private: + DISALLOW_COPY_AND_ASSIGN(TFunction); + + typedef TVector TParamList; + TParamList parameters; + TType returnType; + TString mangledName; + TOperator op; + bool defined; +}; + + +class TSymbolTableLevel { +public: + typedef TMap tLevel; + typedef tLevel::const_iterator const_iterator; + typedef const tLevel::value_type tLevelPair; + typedef std::pair tInsertResult; + + TSymbolTableLevel() { } + ~TSymbolTableLevel(); + + bool insert(const TString &name, TSymbol &symbol) + { + // + // returning true means symbol was added to the table + // + tInsertResult result = level.insert(tLevelPair(name, &symbol)); + + return result.second; + } + + bool insert(TSymbol &symbol) + { + return insert(symbol.getMangledName(), symbol); + } + + TSymbol* find(const TString& name) const + { + tLevel::const_iterator it = level.find(name); + if (it == level.end()) + return 0; + else + return (*it).second; + } + + const_iterator begin() const + { + return level.begin(); + } + + const_iterator end() const + { + return level.end(); + } + + void relateToOperator(const char* name, TOperator op); + void relateToExtension(const char* name, const TString& ext); + void dump(TInfoSink &infoSink) const; + +protected: + tLevel level; +}; + +class TSymbolTable { +public: + TSymbolTable() : uniqueId(0) + { + // + // The symbol table cannot be used until push() is called, but + // the lack of an initial call to push() can be used to detect + // that the symbol table has not been preloaded with built-ins. + // + } + ~TSymbolTable(); + + // + // When the symbol table is initialized with the built-ins, there should + // 'push' calls, so that built-ins are at level 0 and the shader + // globals are at level 1. + // + bool isEmpty() { return table.size() == 0; } + bool atBuiltInLevel() { return table.size() == 1; } + bool atGlobalLevel() { return table.size() <= 2; } + void push() + { + table.push_back(new TSymbolTableLevel); + precisionStack.push_back(new PrecisionStackLevel); + } + + void pop() + { + delete table.back(); + table.pop_back(); + + delete precisionStack.back(); + precisionStack.pop_back(); + } + + bool insert(TSymbol& symbol) + { + symbol.setUniqueId(++uniqueId); + return table[currentLevel()]->insert(symbol); + } + + bool insertConstInt(const char *name, int value) + { + TVariable *constant = new TVariable(NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1)); + constant->getConstPointer()->setIConst(value); + return insert(*constant); + } + + bool insertBuiltIn(TType *rvalue, const char *name, TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0) + { + TFunction *function = new TFunction(NewPoolTString(name), *rvalue); + + TParameter param1 = {NULL, ptype1}; + function->addParameter(param1); + + if(ptype2) + { + TParameter param2 = {NULL, ptype2}; + function->addParameter(param2); + } + + if(ptype3) + { + TParameter param3 = {NULL, ptype3}; + function->addParameter(param3); + } + + return insert(*function); + } + + TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0) + { + int level = currentLevel(); + TSymbol* symbol; + do { + symbol = table[level]->find(name); + --level; + } while (symbol == 0 && level >= 0); + level++; + if (builtIn) + *builtIn = level == 0; + if (sameScope) + *sameScope = level == currentLevel(); + return symbol; + } + + TSymbol* findBuiltIn(const TString &name) + { + return table[0]->find(name); + } + + TSymbolTableLevel* getOuterLevel() { + assert(table.size() >= 2); + return table[currentLevel() - 1]; + } + + void relateToOperator(const char* name, TOperator op) { + table[0]->relateToOperator(name, op); + } + void relateToExtension(const char* name, const TString& ext) { + table[0]->relateToExtension(name, ext); + } + void dump(TInfoSink &infoSink) const; + + bool setDefaultPrecision(const TPublicType& type, TPrecision prec) { + if (!supportsPrecision(type.type)) + return false; + if (type.size != 1 || type.matrix || type.array) + return false; // Not allowed to set for aggregate types + int indexOfLastElement = static_cast(precisionStack.size()) - 1; + (*precisionStack[indexOfLastElement])[type.type] = prec; // Uses map operator [], overwrites the current value + return true; + } + + // Searches down the precisionStack for a precision qualifier for the specified TBasicType + TPrecision getDefaultPrecision(TBasicType type) { + if (!supportsPrecision(type)) + return EbpUndefined; + int level = static_cast(precisionStack.size()) - 1; + assert(level >= 0); // Just to be safe. Should not happen. + PrecisionStackLevel::iterator it; + TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this? + while (level >= 0) { + it = precisionStack[level]->find(type); + if (it != precisionStack[level]->end()) { + prec = (*it).second; + break; + } + level--; + } + return prec; + } + +private: + int currentLevel() const { return static_cast(table.size()) - 1; } + + bool supportsPrecision(TBasicType type) { + // Only supports precision for int, float, and sampler types. + return type == EbtFloat || type == EbtInt || IsSampler(type); + } + + int uniqueId; // for unique identification in code generation + std::vector table; + typedef TMap PrecisionStackLevel; + std::vector precisionStack; +}; + +#endif // _SYMBOL_TABLE_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp new file mode 100644 index 0000000000..9262f7af8c --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp @@ -0,0 +1,43 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/TranslatorESSL.h" + +#include "compiler/translator/OutputESSL.h" + +TranslatorESSL::TranslatorESSL(ShShaderType type, ShShaderSpec spec) + : TCompiler(type, spec) { +} + +void TranslatorESSL::translate(TIntermNode* root) { + TInfoSinkBase& sink = getInfoSink().obj; + + // Write built-in extension behaviors. + writeExtensionBehavior(); + + // Write emulated built-in functions if needed. + getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition( + sink, getShaderType() == SH_FRAGMENT_SHADER); + + // Write array bounds clamping emulation if needed. + getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); + + // Write translated shader. + TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable()); + root->traverse(&outputESSL); +} + +void TranslatorESSL::writeExtensionBehavior() { + TInfoSinkBase& sink = getInfoSink().obj; + const TExtensionBehavior& extensionBehavior = getExtensionBehavior(); + for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin(); + iter != extensionBehavior.end(); ++iter) { + if (iter->second != EBhUndefined) { + sink << "#extension " << iter->first << " : " + << getBehaviorString(iter->second) << "\n"; + } + } +} diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h new file mode 100644 index 0000000000..e18f3c25ec --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h @@ -0,0 +1,23 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATORESSL_H_ +#define COMPILER_TRANSLATORESSL_H_ + +#include "compiler/translator/ShHandle.h" + +class TranslatorESSL : public TCompiler { +public: + TranslatorESSL(ShShaderType type, ShShaderSpec spec); + +protected: + virtual void translate(TIntermNode* root); + +private: + void writeExtensionBehavior(); +}; + +#endif // COMPILER_TRANSLATORESSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp new file mode 100644 index 0000000000..6688d7f362 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp @@ -0,0 +1,44 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/TranslatorGLSL.h" + +#include "compiler/translator/OutputGLSL.h" +#include "compiler/translator/VersionGLSL.h" + +static void writeVersion(ShShaderType type, TIntermNode* root, + TInfoSinkBase& sink) { + TVersionGLSL versionGLSL(type); + root->traverse(&versionGLSL); + int version = versionGLSL.getVersion(); + // We need to write version directive only if it is greater than 110. + // If there is no version directive in the shader, 110 is implied. + if (version > 110) { + sink << "#version " << version << "\n"; + } +} + +TranslatorGLSL::TranslatorGLSL(ShShaderType type, ShShaderSpec spec) + : TCompiler(type, spec) { +} + +void TranslatorGLSL::translate(TIntermNode* root) { + TInfoSinkBase& sink = getInfoSink().obj; + + // Write GLSL version. + writeVersion(getShaderType(), root, sink); + + // Write emulated built-in functions if needed. + getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition( + sink, false); + + // Write array bounds clamping emulation if needed. + getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); + + // Write translated shader. + TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable()); + root->traverse(&outputGLSL); +} diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h new file mode 100644 index 0000000000..40bb3145e8 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h @@ -0,0 +1,20 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATORGLSL_H_ +#define COMPILER_TRANSLATORGLSL_H_ + +#include "compiler/translator/ShHandle.h" + +class TranslatorGLSL : public TCompiler { +public: + TranslatorGLSL(ShShaderType type, ShShaderSpec spec); + +protected: + virtual void translate(TIntermNode* root); +}; + +#endif // COMPILER_TRANSLATORGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp new file mode 100644 index 0000000000..3c1db011b6 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp @@ -0,0 +1,24 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/TranslatorHLSL.h" + +#include "compiler/translator/InitializeParseContext.h" +#include "compiler/translator/OutputHLSL.h" + +TranslatorHLSL::TranslatorHLSL(ShShaderType type, ShShaderSpec spec, ShShaderOutput output) + : TCompiler(type, spec), mOutputType(output) +{ +} + +void TranslatorHLSL::translate(TIntermNode *root) +{ + TParseContext& parseContext = *GetGlobalParseContext(); + sh::OutputHLSL outputHLSL(parseContext, getResources(), mOutputType); + + outputHLSL.output(); + mActiveUniforms = outputHLSL.getUniforms(); +} diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h new file mode 100644 index 0000000000..6204b30cc2 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h @@ -0,0 +1,27 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATORHLSL_H_ +#define COMPILER_TRANSLATORHLSL_H_ + +#include "compiler/translator/ShHandle.h" +#include "compiler/translator/Uniform.h" + +class TranslatorHLSL : public TCompiler { +public: + TranslatorHLSL(ShShaderType type, ShShaderSpec spec, ShShaderOutput output); + + virtual TranslatorHLSL *getAsTranslatorHLSL() { return this; } + const sh::ActiveUniforms &getUniforms() { return mActiveUniforms; } + +protected: + virtual void translate(TIntermNode* root); + + sh::ActiveUniforms mActiveUniforms; + ShShaderOutput mOutputType; +}; + +#endif // COMPILER_TRANSLATORHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Types.h b/src/3rdparty/angle/src/compiler/translator/Types.h new file mode 100644 index 0000000000..119f4f29e5 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/Types.h @@ -0,0 +1,307 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _TYPES_INCLUDED +#define _TYPES_INCLUDED + +#include "common/angleutils.h" + +#include "compiler/translator/BaseTypes.h" +#include "compiler/translator/Common.h" +#include "compiler/translator/compilerdebug.h" + +struct TPublicType; +class TType; + +class TField +{ +public: + POOL_ALLOCATOR_NEW_DELETE(); + TField(TType* type, TString* name) : mType(type), mName(name) {} + + // TODO(alokp): We should only return const type. + // Fix it by tweaking grammar. + TType* type() { return mType; } + const TType* type() const { return mType; } + + const TString& name() const { return *mName; } + +private: + DISALLOW_COPY_AND_ASSIGN(TField); + TType* mType; + TString* mName; +}; + +typedef TVector TFieldList; +inline TFieldList* NewPoolTFieldList() +{ + void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList)); + return new(memory) TFieldList; +} + +class TStructure +{ +public: + POOL_ALLOCATOR_NEW_DELETE(); + TStructure(TString* name, TFieldList* fields) + : mName(name), + mFields(fields), + mObjectSize(0), + mDeepestNesting(0) { + } + + const TString& name() const { return *mName; } + const TFieldList& fields() const { return *mFields; } + + const TString& mangledName() const { + if (mMangledName.empty()) + mMangledName = buildMangledName(); + return mMangledName; + } + size_t objectSize() const { + if (mObjectSize == 0) + mObjectSize = calculateObjectSize(); + return mObjectSize; + }; + int deepestNesting() const { + if (mDeepestNesting == 0) + mDeepestNesting = calculateDeepestNesting(); + return mDeepestNesting; + } + bool containsArrays() const; + +private: + DISALLOW_COPY_AND_ASSIGN(TStructure); + TString buildMangledName() const; + size_t calculateObjectSize() const; + int calculateDeepestNesting() const; + + TString* mName; + TFieldList* mFields; + + mutable TString mMangledName; + mutable size_t mObjectSize; + mutable int mDeepestNesting; +}; + +// +// Base class for things that have a type. +// +class TType +{ +public: + POOL_ALLOCATOR_NEW_DELETE(); + TType() {} + TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, unsigned char s = 1, bool m = false, bool a = false) : + type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), structure(0) + { + } + explicit TType(const TPublicType &p); + TType(TStructure* userDef, TPrecision p = EbpUndefined) : + type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), structure(userDef) + { + } + + TBasicType getBasicType() const { return type; } + void setBasicType(TBasicType t) { type = t; } + + TPrecision getPrecision() const { return precision; } + void setPrecision(TPrecision p) { precision = p; } + + TQualifier getQualifier() const { return qualifier; } + void setQualifier(TQualifier q) { qualifier = q; } + + // One-dimensional size of single instance type + int getNominalSize() const { return size; } + void setNominalSize(unsigned char s) { size = s; } + // Full size of single instance of type + size_t getObjectSize() const; + + int elementRegisterCount() const + { + if (structure) + { + const TFieldList &fields = getStruct()->fields(); + int registerCount = 0; + + for (size_t i = 0; i < fields.size(); i++) + { + registerCount += fields[i]->type()->totalRegisterCount(); + } + + return registerCount; + } + else if (isMatrix()) + { + return getNominalSize(); + } + else + { + return 1; + } + } + + int totalRegisterCount() const + { + if (array) + { + return arraySize * elementRegisterCount(); + } + else + { + return elementRegisterCount(); + } + } + + bool isMatrix() const { return matrix ? true : false; } + void setMatrix(bool m) { matrix = m; } + + bool isArray() const { return array ? true : false; } + int getArraySize() const { return arraySize; } + void setArraySize(int s) { array = true; arraySize = s; } + void clearArrayness() { array = false; arraySize = 0; } + + bool isVector() const { return size > 1 && !matrix; } + bool isScalar() const { return size == 1 && !matrix && !structure; } + + TStructure* getStruct() const { return structure; } + void setStruct(TStructure* s) { structure = s; } + + const TString& getMangledName() const { + if (mangled.empty()) { + mangled = buildMangledName(); + mangled += ';'; + } + return mangled; + } + + bool sameElementType(const TType& right) const { + return type == right.type && + size == right.size && + matrix == right.matrix && + structure == right.structure; + } + bool operator==(const TType& right) const { + return type == right.type && + size == right.size && + matrix == right.matrix && + array == right.array && (!array || arraySize == right.arraySize) && + structure == right.structure; + // don't check the qualifier, it's not ever what's being sought after + } + bool operator!=(const TType& right) const { + return !operator==(right); + } + bool operator<(const TType& right) const { + if (type != right.type) return type < right.type; + if (size != right.size) return size < right.size; + if (matrix != right.matrix) return matrix < right.matrix; + if (array != right.array) return array < right.array; + if (arraySize != right.arraySize) return arraySize < right.arraySize; + if (structure != right.structure) return structure < right.structure; + + return false; + } + + const char* getBasicString() const { return ::getBasicString(type); } + const char* getPrecisionString() const { return ::getPrecisionString(precision); } + const char* getQualifierString() const { return ::getQualifierString(qualifier); } + TString getCompleteString() const; + + // If this type is a struct, returns the deepest struct nesting of + // any field in the struct. For example: + // struct nesting1 { + // vec4 position; + // }; + // struct nesting2 { + // nesting1 field1; + // vec4 field2; + // }; + // For type "nesting2", this method would return 2 -- the number + // of structures through which indirection must occur to reach the + // deepest field (nesting2.field1.position). + int getDeepestStructNesting() const { + return structure ? structure->deepestNesting() : 0; + } + + bool isStructureContainingArrays() const { + return structure ? structure->containsArrays() : false; + } + +private: + TString buildMangledName() const; + + TBasicType type; + TPrecision precision; + TQualifier qualifier; + unsigned char size; + bool matrix; + bool array; + int arraySize; + + TStructure* structure; // 0 unless this is a struct + + mutable TString mangled; +}; + +// +// This is a workaround for a problem with the yacc stack, It can't have +// types that it thinks have non-trivial constructors. It should +// just be used while recognizing the grammar, not anything else. Pointers +// could be used, but also trying to avoid lots of memory management overhead. +// +// Not as bad as it looks, there is no actual assumption that the fields +// match up or are name the same or anything like that. +// +struct TPublicType +{ + TBasicType type; + TQualifier qualifier; + TPrecision precision; + unsigned char size; // size of vector or matrix, not size of array + bool matrix; + bool array; + int arraySize; + TType* userDef; + TSourceLoc line; + + void setBasic(TBasicType bt, TQualifier q, const TSourceLoc& ln) + { + type = bt; + qualifier = q; + precision = EbpUndefined; + size = 1; + matrix = false; + array = false; + arraySize = 0; + userDef = 0; + line = ln; + } + + void setAggregate(unsigned char s, bool m = false) + { + size = s; + matrix = m; + } + + void setArray(bool a, int s = 0) + { + array = a; + arraySize = s; + } + + bool isStructureContainingArrays() const + { + if (!userDef) + { + return false; + } + + return userDef->isStructureContainingArrays(); + } +}; + +#endif // _TYPES_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp new file mode 100644 index 0000000000..b7826119ae --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp @@ -0,0 +1,184 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements. +// The results are assigned to s# temporaries, which are used by the main translator instead of +// the original expression. +// + +#include "compiler/translator/UnfoldShortCircuit.h" + +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/OutputHLSL.h" + +namespace sh +{ +UnfoldShortCircuit::UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL) : mContext(context), mOutputHLSL(outputHLSL) +{ + mTemporaryIndex = 0; +} + +void UnfoldShortCircuit::traverse(TIntermNode *node) +{ + int rewindIndex = mTemporaryIndex; + node->traverse(this); + mTemporaryIndex = rewindIndex; +} + +bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node) +{ + TInfoSinkBase &out = mOutputHLSL->getBodyStream(); + + // If our right node doesn't have side effects, we know we don't need to unfold this + // expression: there will be no short-circuiting side effects to avoid + // (note: unfolding doesn't depend on the left node -- it will always be evaluated) + if (!node->getRight()->hasSideEffects()) + { + return true; + } + + switch (node->getOp()) + { + case EOpLogicalOr: + // "x || y" is equivalent to "x ? true : y", which unfolds to "bool s; if(x) s = true; else s = y;", + // and then further simplifies down to "bool s = x; if(!s) s = y;". + { + int i = mTemporaryIndex; + + out << "bool s" << i << ";\n"; + + out << "{\n"; + + mTemporaryIndex = i + 1; + node->getLeft()->traverse(this); + out << "s" << i << " = "; + mTemporaryIndex = i + 1; + node->getLeft()->traverse(mOutputHLSL); + out << ";\n"; + out << "if (!s" << i << ")\n" + "{\n"; + mTemporaryIndex = i + 1; + node->getRight()->traverse(this); + out << " s" << i << " = "; + mTemporaryIndex = i + 1; + node->getRight()->traverse(mOutputHLSL); + out << ";\n" + "}\n"; + + out << "}\n"; + + mTemporaryIndex = i + 1; + } + return false; + case EOpLogicalAnd: + // "x && y" is equivalent to "x ? y : false", which unfolds to "bool s; if(x) s = y; else s = false;", + // and then further simplifies down to "bool s = x; if(s) s = y;". + { + int i = mTemporaryIndex; + + out << "bool s" << i << ";\n"; + + out << "{\n"; + + mTemporaryIndex = i + 1; + node->getLeft()->traverse(this); + out << "s" << i << " = "; + mTemporaryIndex = i + 1; + node->getLeft()->traverse(mOutputHLSL); + out << ";\n"; + out << "if (s" << i << ")\n" + "{\n"; + mTemporaryIndex = i + 1; + node->getRight()->traverse(this); + out << " s" << i << " = "; + mTemporaryIndex = i + 1; + node->getRight()->traverse(mOutputHLSL); + out << ";\n" + "}\n"; + + out << "}\n"; + + mTemporaryIndex = i + 1; + } + return false; + default: + return true; + } +} + +bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node) +{ + TInfoSinkBase &out = mOutputHLSL->getBodyStream(); + + // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;" + if (node->usesTernaryOperator()) + { + int i = mTemporaryIndex; + + out << mOutputHLSL->typeString(node->getType()) << " s" << i << ";\n"; + + out << "{\n"; + + mTemporaryIndex = i + 1; + node->getCondition()->traverse(this); + out << "if ("; + mTemporaryIndex = i + 1; + node->getCondition()->traverse(mOutputHLSL); + out << ")\n" + "{\n"; + mTemporaryIndex = i + 1; + node->getTrueBlock()->traverse(this); + out << " s" << i << " = "; + mTemporaryIndex = i + 1; + node->getTrueBlock()->traverse(mOutputHLSL); + out << ";\n" + "}\n" + "else\n" + "{\n"; + mTemporaryIndex = i + 1; + node->getFalseBlock()->traverse(this); + out << " s" << i << " = "; + mTemporaryIndex = i + 1; + node->getFalseBlock()->traverse(mOutputHLSL); + out << ";\n" + "}\n"; + + out << "}\n"; + + mTemporaryIndex = i + 1; + } + + return false; +} + +bool UnfoldShortCircuit::visitLoop(Visit visit, TIntermLoop *node) +{ + int rewindIndex = mTemporaryIndex; + + if (node->getInit()) + { + node->getInit()->traverse(this); + } + + if (node->getCondition()) + { + node->getCondition()->traverse(this); + } + + if (node->getExpression()) + { + node->getExpression()->traverse(this); + } + + mTemporaryIndex = rewindIndex; + + return false; +} + +int UnfoldShortCircuit::getNextTemporaryIndex() +{ + return mTemporaryIndex++; +} +} diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h new file mode 100644 index 0000000000..1e416bc04c --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements +// + +#ifndef COMPILER_UNFOLDSHORTCIRCUIT_H_ +#define COMPILER_UNFOLDSHORTCIRCUIT_H_ + +#include "compiler/translator/intermediate.h" +#include "compiler/translator/ParseContext.h" + +namespace sh +{ +class OutputHLSL; + +class UnfoldShortCircuit : public TIntermTraverser +{ + public: + UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL); + + void traverse(TIntermNode *node); + bool visitBinary(Visit visit, TIntermBinary*); + bool visitSelection(Visit visit, TIntermSelection *node); + bool visitLoop(Visit visit, TIntermLoop *node); + + int getNextTemporaryIndex(); + + protected: + TParseContext &mContext; + OutputHLSL *const mOutputHLSL; + + int mTemporaryIndex; +}; +} + +#endif // COMPILER_UNFOLDSHORTCIRCUIT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp new file mode 100644 index 0000000000..29c4397d56 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp @@ -0,0 +1,81 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/UnfoldShortCircuitAST.h" + +namespace +{ + +// "x || y" is equivalent to "x ? true : y". +TIntermSelection *UnfoldOR(TIntermTyped *x, TIntermTyped *y) +{ + const TType boolType(EbtBool, EbpUndefined); + ConstantUnion *u = new ConstantUnion; + u->setBConst(true); + TIntermConstantUnion *trueNode = new TIntermConstantUnion( + u, TType(EbtBool, EbpUndefined, EvqConst, 1)); + return new TIntermSelection(x, trueNode, y, boolType); +} + +// "x && y" is equivalent to "x ? y : false". +TIntermSelection *UnfoldAND(TIntermTyped *x, TIntermTyped *y) +{ + const TType boolType(EbtBool, EbpUndefined); + ConstantUnion *u = new ConstantUnion; + u->setBConst(false); + TIntermConstantUnion *falseNode = new TIntermConstantUnion( + u, TType(EbtBool, EbpUndefined, EvqConst, 1)); + return new TIntermSelection(x, y, falseNode, boolType); +} + +} // namespace anonymous + +bool UnfoldShortCircuitAST::visitBinary(Visit visit, TIntermBinary *node) +{ + TIntermSelection *replacement = NULL; + + switch (node->getOp()) + { + case EOpLogicalOr: + replacement = UnfoldOR(node->getLeft(), node->getRight()); + break; + case EOpLogicalAnd: + replacement = UnfoldAND(node->getLeft(), node->getRight()); + break; + default: + break; + } + if (replacement) + { + replacements.push_back( + NodeUpdateEntry(getParentNode(), node, replacement)); + } + return true; +} + +void UnfoldShortCircuitAST::updateTree() +{ + for (size_t ii = 0; ii < replacements.size(); ++ii) + { + const NodeUpdateEntry& entry = replacements[ii]; + ASSERT(entry.parent); + bool replaced = entry.parent->replaceChildNode( + entry.original, entry.replacement); + ASSERT(replaced); + + // In AST traversing, a parent is visited before its children. + // After we replace a node, if an immediate child is to + // be replaced, we need to make sure we don't update the replaced + // node; instead, we update the replacement node. + for (size_t jj = ii + 1; jj < replacements.size(); ++jj) + { + NodeUpdateEntry& entry2 = replacements[jj]; + if (entry2.parent == entry.original) + entry2.parent = entry.replacement; + } + } +} + diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h new file mode 100644 index 0000000000..24c14a60e3 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h @@ -0,0 +1,51 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// UnfoldShortCircuitAST is an AST traverser to replace short-circuiting +// operations with ternary operations. +// + +#ifndef COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_ +#define COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_ + +#include "common/angleutils.h" +#include "compiler/translator/intermediate.h" + +// This traverser identifies all the short circuit binary nodes that need to +// be replaced, and creates the corresponding replacement nodes. However, +// the actual replacements happen after the traverse through updateTree(). + +class UnfoldShortCircuitAST : public TIntermTraverser +{ + public: + UnfoldShortCircuitAST() { } + + virtual bool visitBinary(Visit visit, TIntermBinary *); + + void updateTree(); + + private: + struct NodeUpdateEntry + { + NodeUpdateEntry(TIntermNode *_parent, + TIntermNode *_original, + TIntermNode *_replacement) + : parent(_parent), + original(_original), + replacement(_replacement) {} + + TIntermNode *parent; + TIntermNode *original; + TIntermNode *replacement; + }; + + // During traversing, save all the replacements that need to happen; + // then replace them by calling updateNodes(). + std::vector replacements; + + DISALLOW_COPY_AND_ASSIGN(UnfoldShortCircuitAST); +}; + +#endif // COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Uniform.cpp b/src/3rdparty/angle/src/compiler/translator/Uniform.cpp new file mode 100644 index 0000000000..922e13f071 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/Uniform.cpp @@ -0,0 +1,21 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/Uniform.h" + +namespace sh +{ + +Uniform::Uniform(GLenum type, GLenum precision, const char *name, int arraySize, int registerIndex) +{ + this->type = type; + this->precision = precision; + this->name = name; + this->arraySize = arraySize; + this->registerIndex = registerIndex; +} + +} diff --git a/src/3rdparty/angle/src/compiler/translator/Uniform.h b/src/3rdparty/angle/src/compiler/translator/Uniform.h new file mode 100644 index 0000000000..4c53ffa7d2 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/Uniform.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_UNIFORM_H_ +#define COMPILER_UNIFORM_H_ + +#include +#include + +#define GL_APICALL +#include + +namespace sh +{ + +struct Uniform +{ + Uniform(GLenum type, GLenum precision, const char *name, int arraySize, int registerIndex); + + GLenum type; + GLenum precision; + std::string name; + unsigned int arraySize; + + int registerIndex; +}; + +typedef std::vector ActiveUniforms; + +} + +#endif // COMPILER_UNIFORM_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp new file mode 100644 index 0000000000..3c2cc41cda --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp @@ -0,0 +1,512 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/ValidateLimitations.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/InitializeParseContext.h" +#include "compiler/translator/ParseContext.h" + +namespace { +bool IsLoopIndex(const TIntermSymbol* symbol, const TLoopStack& stack) { + for (TLoopStack::const_iterator i = stack.begin(); i != stack.end(); ++i) { + if (i->index.id == symbol->getId()) + return true; + } + return false; +} + +void MarkLoopForUnroll(const TIntermSymbol* symbol, TLoopStack& stack) { + for (TLoopStack::iterator i = stack.begin(); i != stack.end(); ++i) { + if (i->index.id == symbol->getId()) { + ASSERT(i->loop != NULL); + i->loop->setUnrollFlag(true); + return; + } + } + UNREACHABLE(); +} + +// Traverses a node to check if it represents a constant index expression. +// Definition: +// constant-index-expressions are a superset of constant-expressions. +// Constant-index-expressions can include loop indices as defined in +// GLSL ES 1.0 spec, Appendix A, section 4. +// The following are constant-index-expressions: +// - Constant expressions +// - Loop indices as defined in section 4 +// - Expressions composed of both of the above +class ValidateConstIndexExpr : public TIntermTraverser { +public: + ValidateConstIndexExpr(const TLoopStack& stack) + : mValid(true), mLoopStack(stack) {} + + // Returns true if the parsed node represents a constant index expression. + bool isValid() const { return mValid; } + + virtual void visitSymbol(TIntermSymbol* symbol) { + // Only constants and loop indices are allowed in a + // constant index expression. + if (mValid) { + mValid = (symbol->getQualifier() == EvqConst) || + IsLoopIndex(symbol, mLoopStack); + } + } + +private: + bool mValid; + const TLoopStack& mLoopStack; +}; + +// Traverses a node to check if it uses a loop index. +// If an int loop index is used in its body as a sampler array index, +// mark the loop for unroll. +class ValidateLoopIndexExpr : public TIntermTraverser { +public: + ValidateLoopIndexExpr(TLoopStack& stack) + : mUsesFloatLoopIndex(false), + mUsesIntLoopIndex(false), + mLoopStack(stack) {} + + bool usesFloatLoopIndex() const { return mUsesFloatLoopIndex; } + bool usesIntLoopIndex() const { return mUsesIntLoopIndex; } + + virtual void visitSymbol(TIntermSymbol* symbol) { + if (IsLoopIndex(symbol, mLoopStack)) { + switch (symbol->getBasicType()) { + case EbtFloat: + mUsesFloatLoopIndex = true; + break; + case EbtInt: + mUsesIntLoopIndex = true; + MarkLoopForUnroll(symbol, mLoopStack); + break; + default: + UNREACHABLE(); + } + } + } + +private: + bool mUsesFloatLoopIndex; + bool mUsesIntLoopIndex; + TLoopStack& mLoopStack; +}; +} // namespace + +ValidateLimitations::ValidateLimitations(ShShaderType shaderType, + TInfoSinkBase& sink) + : mShaderType(shaderType), + mSink(sink), + mNumErrors(0) +{ +} + +bool ValidateLimitations::visitBinary(Visit, TIntermBinary* node) +{ + // Check if loop index is modified in the loop body. + validateOperation(node, node->getLeft()); + + // Check indexing. + switch (node->getOp()) { + case EOpIndexDirect: + validateIndexing(node); + break; + case EOpIndexIndirect: +#if defined(__APPLE__) + // Loop unrolling is a work-around for a Mac Cg compiler bug where it + // crashes when a sampler array's index is also the loop index. + // Once Apple fixes this bug, we should remove the code in this CL. + // See http://codereview.appspot.com/4331048/. + if ((node->getLeft() != NULL) && (node->getRight() != NULL) && + (node->getLeft()->getAsSymbolNode())) { + TIntermSymbol* symbol = node->getLeft()->getAsSymbolNode(); + if (IsSampler(symbol->getBasicType()) && symbol->isArray()) { + ValidateLoopIndexExpr validate(mLoopStack); + node->getRight()->traverse(&validate); + if (validate.usesFloatLoopIndex()) { + error(node->getLine(), + "sampler array index is float loop index", + "for"); + } + } + } +#endif + validateIndexing(node); + break; + default: break; + } + return true; +} + +bool ValidateLimitations::visitUnary(Visit, TIntermUnary* node) +{ + // Check if loop index is modified in the loop body. + validateOperation(node, node->getOperand()); + + return true; +} + +bool ValidateLimitations::visitAggregate(Visit, TIntermAggregate* node) +{ + switch (node->getOp()) { + case EOpFunctionCall: + validateFunctionCall(node); + break; + default: + break; + } + return true; +} + +bool ValidateLimitations::visitLoop(Visit, TIntermLoop* node) +{ + if (!validateLoopType(node)) + return false; + + TLoopInfo info; + memset(&info, 0, sizeof(TLoopInfo)); + info.loop = node; + if (!validateForLoopHeader(node, &info)) + return false; + + TIntermNode* body = node->getBody(); + if (body != NULL) { + mLoopStack.push_back(info); + body->traverse(this); + mLoopStack.pop_back(); + } + + // The loop is fully processed - no need to visit children. + return false; +} + +void ValidateLimitations::error(TSourceLoc loc, + const char *reason, const char* token) +{ + mSink.prefix(EPrefixError); + mSink.location(loc); + mSink << "'" << token << "' : " << reason << "\n"; + ++mNumErrors; +} + +bool ValidateLimitations::withinLoopBody() const +{ + return !mLoopStack.empty(); +} + +bool ValidateLimitations::isLoopIndex(const TIntermSymbol* symbol) const +{ + return IsLoopIndex(symbol, mLoopStack); +} + +bool ValidateLimitations::validateLoopType(TIntermLoop* node) { + TLoopType type = node->getType(); + if (type == ELoopFor) + return true; + + // Reject while and do-while loops. + error(node->getLine(), + "This type of loop is not allowed", + type == ELoopWhile ? "while" : "do"); + return false; +} + +bool ValidateLimitations::validateForLoopHeader(TIntermLoop* node, + TLoopInfo* info) +{ + ASSERT(node->getType() == ELoopFor); + + // + // The for statement has the form: + // for ( init-declaration ; condition ; expression ) statement + // + if (!validateForLoopInit(node, info)) + return false; + if (!validateForLoopCond(node, info)) + return false; + if (!validateForLoopExpr(node, info)) + return false; + + return true; +} + +bool ValidateLimitations::validateForLoopInit(TIntermLoop* node, + TLoopInfo* info) +{ + TIntermNode* init = node->getInit(); + if (init == NULL) { + error(node->getLine(), "Missing init declaration", "for"); + return false; + } + + // + // init-declaration has the form: + // type-specifier identifier = constant-expression + // + TIntermAggregate* decl = init->getAsAggregate(); + if ((decl == NULL) || (decl->getOp() != EOpDeclaration)) { + error(init->getLine(), "Invalid init declaration", "for"); + return false; + } + // To keep things simple do not allow declaration list. + TIntermSequence& declSeq = decl->getSequence(); + if (declSeq.size() != 1) { + error(decl->getLine(), "Invalid init declaration", "for"); + return false; + } + TIntermBinary* declInit = declSeq[0]->getAsBinaryNode(); + if ((declInit == NULL) || (declInit->getOp() != EOpInitialize)) { + error(decl->getLine(), "Invalid init declaration", "for"); + return false; + } + TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode(); + if (symbol == NULL) { + error(declInit->getLine(), "Invalid init declaration", "for"); + return false; + } + // The loop index has type int or float. + TBasicType type = symbol->getBasicType(); + if ((type != EbtInt) && (type != EbtFloat)) { + error(symbol->getLine(), + "Invalid type for loop index", getBasicString(type)); + return false; + } + // The loop index is initialized with constant expression. + if (!isConstExpr(declInit->getRight())) { + error(declInit->getLine(), + "Loop index cannot be initialized with non-constant expression", + symbol->getSymbol().c_str()); + return false; + } + + info->index.id = symbol->getId(); + return true; +} + +bool ValidateLimitations::validateForLoopCond(TIntermLoop* node, + TLoopInfo* info) +{ + TIntermNode* cond = node->getCondition(); + if (cond == NULL) { + error(node->getLine(), "Missing condition", "for"); + return false; + } + // + // condition has the form: + // loop_index relational_operator constant_expression + // + TIntermBinary* binOp = cond->getAsBinaryNode(); + if (binOp == NULL) { + error(node->getLine(), "Invalid condition", "for"); + return false; + } + // Loop index should be to the left of relational operator. + TIntermSymbol* symbol = binOp->getLeft()->getAsSymbolNode(); + if (symbol == NULL) { + error(binOp->getLine(), "Invalid condition", "for"); + return false; + } + if (symbol->getId() != info->index.id) { + error(symbol->getLine(), + "Expected loop index", symbol->getSymbol().c_str()); + return false; + } + // Relational operator is one of: > >= < <= == or !=. + switch (binOp->getOp()) { + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + break; + default: + error(binOp->getLine(), + "Invalid relational operator", + getOperatorString(binOp->getOp())); + break; + } + // Loop index must be compared with a constant. + if (!isConstExpr(binOp->getRight())) { + error(binOp->getLine(), + "Loop index cannot be compared with non-constant expression", + symbol->getSymbol().c_str()); + return false; + } + + return true; +} + +bool ValidateLimitations::validateForLoopExpr(TIntermLoop* node, + TLoopInfo* info) +{ + TIntermNode* expr = node->getExpression(); + if (expr == NULL) { + error(node->getLine(), "Missing expression", "for"); + return false; + } + + // for expression has one of the following forms: + // loop_index++ + // loop_index-- + // loop_index += constant_expression + // loop_index -= constant_expression + // ++loop_index + // --loop_index + // The last two forms are not specified in the spec, but I am assuming + // its an oversight. + TIntermUnary* unOp = expr->getAsUnaryNode(); + TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode(); + + TOperator op = EOpNull; + TIntermSymbol* symbol = NULL; + if (unOp != NULL) { + op = unOp->getOp(); + symbol = unOp->getOperand()->getAsSymbolNode(); + } else if (binOp != NULL) { + op = binOp->getOp(); + symbol = binOp->getLeft()->getAsSymbolNode(); + } + + // The operand must be loop index. + if (symbol == NULL) { + error(expr->getLine(), "Invalid expression", "for"); + return false; + } + if (symbol->getId() != info->index.id) { + error(symbol->getLine(), + "Expected loop index", symbol->getSymbol().c_str()); + return false; + } + + // The operator is one of: ++ -- += -=. + switch (op) { + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + ASSERT((unOp != NULL) && (binOp == NULL)); + break; + case EOpAddAssign: + case EOpSubAssign: + ASSERT((unOp == NULL) && (binOp != NULL)); + break; + default: + error(expr->getLine(), "Invalid operator", getOperatorString(op)); + return false; + } + + // Loop index must be incremented/decremented with a constant. + if (binOp != NULL) { + if (!isConstExpr(binOp->getRight())) { + error(binOp->getLine(), + "Loop index cannot be modified by non-constant expression", + symbol->getSymbol().c_str()); + return false; + } + } + + return true; +} + +bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node) +{ + ASSERT(node->getOp() == EOpFunctionCall); + + // If not within loop body, there is nothing to check. + if (!withinLoopBody()) + return true; + + // List of param indices for which loop indices are used as argument. + typedef std::vector 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 = GetGlobalParseContext()->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->isAssignment()) + return true; + + const TIntermSymbol* symbol = operand->getAsSymbolNode(); + if (symbol && isLoopIndex(symbol)) { + error(node->getLine(), + "Loop index cannot be statically assigned to within the body of the loop", + symbol->getSymbol().c_str()); + } + return true; +} + +bool ValidateLimitations::isConstExpr(TIntermNode* node) +{ + ASSERT(node != NULL); + return node->getAsConstantUnion() != NULL; +} + +bool ValidateLimitations::isConstIndexExpr(TIntermNode* node) +{ + ASSERT(node != NULL); + + ValidateConstIndexExpr validate(mLoopStack); + node->traverse(&validate); + return validate.isValid(); +} + +bool ValidateLimitations::validateIndexing(TIntermBinary* node) +{ + ASSERT((node->getOp() == EOpIndexDirect) || + (node->getOp() == EOpIndexIndirect)); + + bool valid = true; + TIntermTyped* index = node->getRight(); + // The index expression must have integral type. + if (!index->isScalar() || (index->getBasicType() != EbtInt)) { + error(index->getLine(), + "Index expression must have integral type", + index->getCompleteString().c_str()); + valid = false; + } + // The index expession must be a constant-index-expression unless + // the operand is a uniform in a vertex shader. + TIntermTyped* operand = node->getLeft(); + bool skip = (mShaderType == SH_VERTEX_SHADER) && + (operand->getQualifier() == EvqUniform); + if (!skip && !isConstIndexExpr(index)) { + error(index->getLine(), "Index expression must be constant", "[]"); + valid = false; + } + return valid; +} + diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h new file mode 100644 index 0000000000..8839dd8b8a --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h @@ -0,0 +1,59 @@ +// +// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "GLSLANG/ShaderLang.h" +#include "compiler/translator/intermediate.h" + +class TInfoSinkBase; + +struct TLoopInfo { + struct TIndex { + int id; // symbol id. + } index; + TIntermLoop* loop; +}; +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 bool visitBinary(Visit, TIntermBinary*); + virtual bool visitUnary(Visit, TIntermUnary*); + virtual bool visitAggregate(Visit, TIntermAggregate*); + virtual bool visitLoop(Visit, TIntermLoop*); + +private: + void error(TSourceLoc loc, const char *reason, const char* token); + + bool withinLoopBody() const; + bool isLoopIndex(const TIntermSymbol* symbol) const; + bool validateLoopType(TIntermLoop* node); + bool validateForLoopHeader(TIntermLoop* node, TLoopInfo* info); + bool validateForLoopInit(TIntermLoop* node, TLoopInfo* info); + bool validateForLoopCond(TIntermLoop* node, TLoopInfo* info); + bool validateForLoopExpr(TIntermLoop* node, TLoopInfo* info); + // Returns true if none of the loop indices is used as the argument to + // the given function out or inout parameter. + bool validateFunctionCall(TIntermAggregate* node); + bool validateOperation(TIntermOperator* node, TIntermNode* operand); + + // Returns true if indexing does not exceed the minimum functionality + // mandated in GLSL 1.0 spec, Appendix A, Section 5. + bool isConstExpr(TIntermNode* node); + bool isConstIndexExpr(TIntermNode* node); + bool validateIndexing(TIntermBinary* node); + + ShShaderType mShaderType; + TInfoSinkBase& mSink; + int mNumErrors; + TLoopStack mLoopStack; +}; + diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp new file mode 100644 index 0000000000..ef888aff11 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp @@ -0,0 +1,312 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/VariableInfo.h" + +namespace { + +TString arrayBrackets(int index) +{ + TStringStream stream; + stream << "[" << index << "]"; + return stream.str(); +} + +// Returns the data type for an attribute, uniform, or varying. +ShDataType getVariableDataType(const TType& type) +{ + switch (type.getBasicType()) { + case EbtFloat: + if (type.isMatrix()) { + switch (type.getNominalSize()) { + case 2: return SH_FLOAT_MAT2; + case 3: return SH_FLOAT_MAT3; + case 4: return SH_FLOAT_MAT4; + default: UNREACHABLE(); + } + } else if (type.isVector()) { + switch (type.getNominalSize()) { + case 2: return SH_FLOAT_VEC2; + case 3: return SH_FLOAT_VEC3; + case 4: return SH_FLOAT_VEC4; + default: UNREACHABLE(); + } + } else { + return SH_FLOAT; + } + case EbtInt: + if (type.isMatrix()) { + UNREACHABLE(); + } else if (type.isVector()) { + switch (type.getNominalSize()) { + case 2: return SH_INT_VEC2; + case 3: return SH_INT_VEC3; + case 4: return SH_INT_VEC4; + default: UNREACHABLE(); + } + } else { + return SH_INT; + } + case EbtBool: + if (type.isMatrix()) { + UNREACHABLE(); + } else if (type.isVector()) { + switch (type.getNominalSize()) { + case 2: return SH_BOOL_VEC2; + case 3: return SH_BOOL_VEC3; + case 4: return SH_BOOL_VEC4; + default: UNREACHABLE(); + } + } else { + return SH_BOOL; + } + case EbtSampler2D: return SH_SAMPLER_2D; + case EbtSamplerCube: return SH_SAMPLER_CUBE; + case EbtSamplerExternalOES: return SH_SAMPLER_EXTERNAL_OES; + case EbtSampler2DRect: return SH_SAMPLER_2D_RECT_ARB; + default: UNREACHABLE(); + } + return SH_NONE; +} + +void getBuiltInVariableInfo(const TType& type, + const TString& name, + const TString& mappedName, + TVariableInfoList& infoList); +void getUserDefinedVariableInfo(const TType& type, + const TString& name, + const TString& mappedName, + TVariableInfoList& infoList, + ShHashFunction64 hashFunction); + +// Returns info for an attribute, uniform, or varying. +void getVariableInfo(const TType& type, + const TString& name, + const TString& mappedName, + TVariableInfoList& infoList, + ShHashFunction64 hashFunction) +{ + if (type.getBasicType() == EbtStruct) { + if (type.isArray()) { + for (int i = 0; i < type.getArraySize(); ++i) { + TString lname = name + arrayBrackets(i); + TString lmappedName = mappedName + arrayBrackets(i); + getUserDefinedVariableInfo(type, lname, lmappedName, infoList, hashFunction); + } + } else { + getUserDefinedVariableInfo(type, name, mappedName, infoList, hashFunction); + } + } else { + getBuiltInVariableInfo(type, name, mappedName, infoList); + } +} + +void getBuiltInVariableInfo(const TType& type, + const TString& name, + const TString& mappedName, + TVariableInfoList& infoList) +{ + ASSERT(type.getBasicType() != EbtStruct); + + TVariableInfo varInfo; + if (type.isArray()) { + varInfo.name = (name + "[0]").c_str(); + varInfo.mappedName = (mappedName + "[0]").c_str(); + varInfo.size = type.getArraySize(); + varInfo.isArray = true; + } else { + varInfo.name = name.c_str(); + varInfo.mappedName = mappedName.c_str(); + varInfo.size = 1; + varInfo.isArray = false; + } + varInfo.precision = type.getPrecision(); + varInfo.type = getVariableDataType(type); + infoList.push_back(varInfo); +} + +void getUserDefinedVariableInfo(const TType& type, + const TString& name, + const TString& mappedName, + TVariableInfoList& infoList, + ShHashFunction64 hashFunction) +{ + ASSERT(type.getBasicType() == EbtStruct); + + const TFieldList& fields = type.getStruct()->fields(); + for (size_t i = 0; i < fields.size(); ++i) { + const TType& fieldType = *(fields[i]->type()); + const TString& fieldName = fields[i]->name(); + getVariableInfo(fieldType, + name + "." + fieldName, + mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction), + infoList, + hashFunction); + } +} + +TVariableInfo* findVariable(const TType& type, + const TString& name, + TVariableInfoList& infoList) +{ + // TODO(zmo): optimize this function. + TString myName = name; + if (type.isArray()) + myName += "[0]"; + for (size_t ii = 0; ii < infoList.size(); ++ii) + { + if (infoList[ii].name.c_str() == myName) + return &(infoList[ii]); + } + return NULL; +} + +} // namespace anonymous + +TVariableInfo::TVariableInfo() + : type(SH_NONE), + size(0), + isArray(false), + precision(EbpUndefined), + staticUse(false) +{ +} + +TVariableInfo::TVariableInfo(ShDataType type, int size) + : type(type), + size(size), + isArray(false), + precision(EbpUndefined), + staticUse(false) +{ +} + +CollectVariables::CollectVariables(TVariableInfoList& attribs, + TVariableInfoList& uniforms, + TVariableInfoList& varyings, + ShHashFunction64 hashFunction) + : mAttribs(attribs), + mUniforms(uniforms), + mVaryings(varyings), + mPointCoordAdded(false), + mFrontFacingAdded(false), + mFragCoordAdded(false), + mHashFunction(hashFunction) +{ +} + +// We want to check whether a uniform/varying is statically used +// because we only count the used ones in packing computing. +// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count +// toward varying counting if they are statically used in a fragment +// shader. +void CollectVariables::visitSymbol(TIntermSymbol* symbol) +{ + ASSERT(symbol != NULL); + TVariableInfo* var = NULL; + switch (symbol->getQualifier()) + { + case EvqVaryingOut: + case EvqInvariantVaryingOut: + case EvqVaryingIn: + case EvqInvariantVaryingIn: + var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings); + break; + case EvqUniform: + var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms); + break; + case EvqFragCoord: + if (!mFragCoordAdded) { + TVariableInfo info; + info.name = "gl_FragCoord"; + info.mappedName = "gl_FragCoord"; + info.type = SH_FLOAT_VEC4; + info.size = 1; + info.precision = EbpMedium; // Use mediump as it doesn't really matter. + info.staticUse = true; + mVaryings.push_back(info); + mFragCoordAdded = true; + } + return; + case EvqFrontFacing: + if (!mFrontFacingAdded) { + TVariableInfo info; + info.name = "gl_FrontFacing"; + info.mappedName = "gl_FrontFacing"; + info.type = SH_BOOL; + info.size = 1; + info.precision = EbpUndefined; + info.staticUse = true; + mVaryings.push_back(info); + mFrontFacingAdded = true; + } + return; + case EvqPointCoord: + if (!mPointCoordAdded) { + TVariableInfo info; + info.name = "gl_PointCoord"; + info.mappedName = "gl_PointCoord"; + info.type = SH_FLOAT_VEC2; + info.size = 1; + info.precision = EbpMedium; // Use mediump as it doesn't really matter. + info.staticUse = true; + mVaryings.push_back(info); + mPointCoordAdded = true; + } + return; + default: + break; + } + if (var) + var->staticUse = true; +} + +bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node) +{ + bool visitChildren = true; + + switch (node->getOp()) + { + case EOpDeclaration: { + const TIntermSequence& sequence = node->getSequence(); + TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier(); + if (qualifier == EvqAttribute || qualifier == EvqUniform || + qualifier == EvqVaryingIn || qualifier == EvqVaryingOut || + qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut) + { + TVariableInfoList& infoList = qualifier == EvqAttribute ? mAttribs : + (qualifier == EvqUniform ? mUniforms : mVaryings); + 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, uniforms, + // and varyings cannot be initialized in a shader, we must have + // only TIntermSymbol nodes in the sequence. + ASSERT(variable != NULL); + TString processedSymbol; + if (mHashFunction == NULL) + processedSymbol = variable->getSymbol(); + else + processedSymbol = TIntermTraverser::hash(variable->getOriginalSymbol(), mHashFunction); + getVariableInfo(variable->getType(), + variable->getOriginalSymbol(), + processedSymbol, + infoList, + mHashFunction); + visitChildren = false; + } + } + break; + } + default: break; + } + + return visitChildren; +} + diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h new file mode 100644 index 0000000000..37216cd142 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h @@ -0,0 +1,52 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_VARIABLE_INFO_H_ +#define COMPILER_VARIABLE_INFO_H_ + +#include "GLSLANG/ShaderLang.h" +#include "compiler/translator/intermediate.h" + +// Provides information about a variable. +// It is currently being used to store info about active attribs and uniforms. +struct TVariableInfo { + TVariableInfo(ShDataType type, int size); + TVariableInfo(); + + TPersistString name; + TPersistString mappedName; + ShDataType type; + int size; + bool isArray; + TPrecision precision; + bool staticUse; +}; +typedef std::vector TVariableInfoList; + +// Traverses intermediate tree to collect all attributes, uniforms, varyings. +class CollectVariables : public TIntermTraverser { +public: + CollectVariables(TVariableInfoList& attribs, + TVariableInfoList& uniforms, + TVariableInfoList& varyings, + ShHashFunction64 hashFunction); + + virtual void visitSymbol(TIntermSymbol*); + virtual bool visitAggregate(Visit, TIntermAggregate*); + +private: + TVariableInfoList& mAttribs; + TVariableInfoList& mUniforms; + TVariableInfoList& mVaryings; + + bool mPointCoordAdded; + bool mFrontFacingAdded; + bool mFragCoordAdded; + + ShHashFunction64 mHashFunction; +}; + +#endif // COMPILER_VARIABLE_INFO_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp b/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp new file mode 100644 index 0000000000..5634d86337 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp @@ -0,0 +1,297 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +#include "compiler/translator/VariablePacker.h" + +#include +#include "compiler/translator/ShHandle.h" + +namespace { +int GetSortOrder(ShDataType type) +{ + switch (type) { + case SH_FLOAT_MAT4: + return 0; + case SH_FLOAT_MAT2: + return 1; + case SH_FLOAT_VEC4: + case SH_INT_VEC4: + case SH_BOOL_VEC4: + return 2; + case SH_FLOAT_MAT3: + return 3; + case SH_FLOAT_VEC3: + case SH_INT_VEC3: + case SH_BOOL_VEC3: + return 4; + case SH_FLOAT_VEC2: + case SH_INT_VEC2: + case SH_BOOL_VEC2: + return 5; + case SH_FLOAT: + case SH_INT: + case SH_BOOL: + case SH_SAMPLER_2D: + case SH_SAMPLER_CUBE: + case SH_SAMPLER_EXTERNAL_OES: + case SH_SAMPLER_2D_RECT_ARB: + return 6; + default: + ASSERT(false); + return 7; + } +} +} // namespace + +int VariablePacker::GetNumComponentsPerRow(ShDataType type) +{ + switch (type) { + case SH_FLOAT_MAT4: + case SH_FLOAT_MAT2: + case SH_FLOAT_VEC4: + case SH_INT_VEC4: + case SH_BOOL_VEC4: + return 4; + case SH_FLOAT_MAT3: + case SH_FLOAT_VEC3: + case SH_INT_VEC3: + case SH_BOOL_VEC3: + return 3; + case SH_FLOAT_VEC2: + case SH_INT_VEC2: + case SH_BOOL_VEC2: + return 2; + case SH_FLOAT: + case SH_INT: + case SH_BOOL: + case SH_SAMPLER_2D: + case SH_SAMPLER_CUBE: + case SH_SAMPLER_EXTERNAL_OES: + case SH_SAMPLER_2D_RECT_ARB: + return 1; + default: + ASSERT(false); + return 5; + } +} + +int VariablePacker::GetNumRows(ShDataType type) +{ + switch (type) { + case SH_FLOAT_MAT4: + return 4; + case SH_FLOAT_MAT3: + return 3; + case SH_FLOAT_MAT2: + return 2; + case SH_FLOAT_VEC4: + case SH_INT_VEC4: + case SH_BOOL_VEC4: + case SH_FLOAT_VEC3: + case SH_INT_VEC3: + case SH_BOOL_VEC3: + case SH_FLOAT_VEC2: + case SH_INT_VEC2: + case SH_BOOL_VEC2: + case SH_FLOAT: + case SH_INT: + case SH_BOOL: + case SH_SAMPLER_2D: + case SH_SAMPLER_CUBE: + case SH_SAMPLER_EXTERNAL_OES: + case SH_SAMPLER_2D_RECT_ARB: + return 1; + default: + ASSERT(false); + return 100000; + } +} + +struct TVariableInfoComparer { + bool operator()(const TVariableInfo& lhs, const TVariableInfo& rhs) const + { + int lhsSortOrder = GetSortOrder(lhs.type); + int rhsSortOrder = GetSortOrder(rhs.type); + if (lhsSortOrder != rhsSortOrder) { + return lhsSortOrder < rhsSortOrder; + } + // Sort by largest first. + return lhs.size > rhs.size; + } +}; + +unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow) +{ + return ((kColumnMask << (kNumColumns - numComponentsPerRow)) & + kColumnMask) >> column; +} + +void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow) +{ + unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow); + for (int r = 0; r < numRows; ++r) { + int row = topRow + r; + ASSERT((rows_[row] & columnFlags) == 0); + rows_[row] |= columnFlags; + } +} + +bool VariablePacker::searchColumn(int column, int numRows, int* destRow, int* destSize) +{ + ASSERT(destRow); + + for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask; + ++topNonFullRow_) { + } + + for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask; + --bottomNonFullRow_) { + } + + if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows) { + return false; + } + + unsigned columnFlags = makeColumnFlags(column, 1); + int topGoodRow = 0; + int smallestGoodTop = -1; + int smallestGoodSize = maxRows_ + 1; + int bottomRow = bottomNonFullRow_ + 1; + bool found = false; + for (int row = topNonFullRow_; row <= bottomRow; ++row) { + bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false; + if (rowEmpty) { + if (!found) { + topGoodRow = row; + found = true; + } + } else { + if (found) { + int size = row - topGoodRow; + if (size >= numRows && size < smallestGoodSize) { + smallestGoodSize = size; + smallestGoodTop = topGoodRow; + } + } + found = false; + } + } + if (smallestGoodTop < 0) { + return false; + } + + *destRow = smallestGoodTop; + if (destSize) { + *destSize = smallestGoodSize; + } + return true; +} + +bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVariableInfoList& in_variables) +{ + ASSERT(maxVectors > 0); + maxRows_ = maxVectors; + topNonFullRow_ = 0; + bottomNonFullRow_ = maxRows_ - 1; + TVariableInfoList variables(in_variables); + + // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific + // order by type, then by size of array, largest first. + std::sort(variables.begin(), variables.end(), TVariableInfoComparer()); + rows_.clear(); + rows_.resize(maxVectors, 0); + + // Packs the 4 column variables. + size_t ii = 0; + for (; ii < variables.size(); ++ii) { + const TVariableInfo& variable = variables[ii]; + if (GetNumComponentsPerRow(variable.type) != 4) { + break; + } + topNonFullRow_ += GetNumRows(variable.type) * variable.size; + } + + if (topNonFullRow_ > maxRows_) { + return false; + } + + // Packs the 3 column variables. + int num3ColumnRows = 0; + for (; ii < variables.size(); ++ii) { + const TVariableInfo& variable = variables[ii]; + if (GetNumComponentsPerRow(variable.type) != 3) { + break; + } + num3ColumnRows += GetNumRows(variable.type) * variable.size; + } + + if (topNonFullRow_ + num3ColumnRows > maxRows_) { + return false; + } + + fillColumns(topNonFullRow_, num3ColumnRows, 0, 3); + + // Packs the 2 column variables. + int top2ColumnRow = topNonFullRow_ + num3ColumnRows; + int twoColumnRowsAvailable = maxRows_ - top2ColumnRow; + int rowsAvailableInColumns01 = twoColumnRowsAvailable; + int rowsAvailableInColumns23 = twoColumnRowsAvailable; + for (; ii < variables.size(); ++ii) { + const TVariableInfo& variable = variables[ii]; + if (GetNumComponentsPerRow(variable.type) != 2) { + break; + } + int numRows = GetNumRows(variable.type) * variable.size; + if (numRows <= rowsAvailableInColumns01) { + rowsAvailableInColumns01 -= numRows; + } else if (numRows <= rowsAvailableInColumns23) { + rowsAvailableInColumns23 -= numRows; + } else { + return false; + } + } + + int numRowsUsedInColumns01 = + twoColumnRowsAvailable - rowsAvailableInColumns01; + int numRowsUsedInColumns23 = + twoColumnRowsAvailable - rowsAvailableInColumns23; + fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2); + fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23, + 2, 2); + + // Packs the 1 column variables. + for (; ii < variables.size(); ++ii) { + const TVariableInfo& variable = variables[ii]; + ASSERT(1 == GetNumComponentsPerRow(variable.type)); + int numRows = GetNumRows(variable.type) * variable.size; + int smallestColumn = -1; + int smallestSize = maxRows_ + 1; + int topRow = -1; + for (int column = 0; column < kNumColumns; ++column) { + int row = 0; + int size = 0; + if (searchColumn(column, numRows, &row, &size)) { + if (size < smallestSize) { + smallestSize = size; + smallestColumn = column; + topRow = row; + } + } + } + + if (smallestColumn < 0) { + return false; + } + + fillColumns(topRow, numRows, smallestColumn, 1); + } + + ASSERT(variables.size() == ii); + + return true; +} + + + diff --git a/src/3rdparty/angle/src/compiler/translator/VariablePacker.h b/src/3rdparty/angle/src/compiler/translator/VariablePacker.h new file mode 100644 index 0000000000..fd6090827c --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/VariablePacker.h @@ -0,0 +1,41 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _VARIABLEPACKER_INCLUDED_ +#define _VARIABLEPACKER_INCLUDED_ + +#include +#include "compiler/translator/ShHandle.h" + +class VariablePacker { + public: + // Returns true if the passed in variables pack in maxVectors following + // the packing rules from the GLSL 1.017 spec, Appendix A, section 7. + bool CheckVariablesWithinPackingLimits( + int maxVectors, + const TVariableInfoList& in_variables); + + // Gets how many components in a row a data type takes. + static int GetNumComponentsPerRow(ShDataType type); + + // Gets how many rows a data type takes. + static int GetNumRows(ShDataType type); + + private: + static const int kNumColumns = 4; + static const unsigned kColumnMask = (1 << kNumColumns) - 1; + + unsigned makeColumnFlags(int column, int numComponentsPerRow); + void fillColumns(int topRow, int numRows, int column, int numComponentsPerRow); + bool searchColumn(int column, int numRows, int* destRow, int* destSize); + + int topNonFullRow_; + int bottomNonFullRow_; + int maxRows_; + std::vector rows_; +}; + +#endif // _VARIABLEPACKER_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp new file mode 100644 index 0000000000..dd11f99eb8 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp @@ -0,0 +1,140 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/VersionGLSL.h" + +static const int GLSL_VERSION_110 = 110; +static const int GLSL_VERSION_120 = 120; + +// We need to scan for the following: +// 1. "invariant" keyword: This can occur in both - vertex and fragment shaders +// but only at the global scope. +// 2. "gl_PointCoord" built-in variable: This can only occur in fragment shader +// but inside any scope. +// 3. Call to a matrix constructor with another matrix as argument. +// (These constructors were reserved in GLSL version 1.10.) +// 4. Arrays as "out" function parameters. +// GLSL spec section 6.1.1: "When calling a function, expressions that do +// not evaluate to l-values cannot be passed to parameters declared as +// out or inout." +// GLSL 1.1 section 5.8: "Other binary or unary expressions, +// non-dereferenced arrays, function names, swizzles with repeated fields, +// and constants cannot be l-values." +// GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that +// are built-in types, entire structures or arrays... are all l-values." +// +// TODO(alokp): The following two cases of invariant decalaration get lost +// during parsing - they do not get carried over to the intermediate tree. +// Handle these cases: +// 1. When a pragma is used to force all output variables to be invariant: +// - #pragma STDGL invariant(all) +// 2. When a previously decalared or built-in variable is marked invariant: +// - invariant gl_Position; +// - varying vec3 color; invariant color; +// +TVersionGLSL::TVersionGLSL(ShShaderType type) + : mShaderType(type), + mVersion(GLSL_VERSION_110) +{ +} + +void TVersionGLSL::visitSymbol(TIntermSymbol* node) +{ + if (node->getSymbol() == "gl_PointCoord") + updateVersion(GLSL_VERSION_120); +} + +void TVersionGLSL::visitConstantUnion(TIntermConstantUnion*) +{ +} + +bool TVersionGLSL::visitBinary(Visit, TIntermBinary*) +{ + return true; +} + +bool TVersionGLSL::visitUnary(Visit, TIntermUnary*) +{ + return true; +} + +bool TVersionGLSL::visitSelection(Visit, TIntermSelection*) +{ + return true; +} + +bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate* node) +{ + bool visitChildren = true; + + switch (node->getOp()) { + case EOpSequence: + // We need to visit sequence children to get to global or inner scope. + visitChildren = true; + break; + case EOpDeclaration: { + const TIntermSequence& sequence = node->getSequence(); + TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier(); + if ((qualifier == EvqInvariantVaryingIn) || + (qualifier == EvqInvariantVaryingOut)) { + updateVersion(GLSL_VERSION_120); + } + break; + } + case EOpParameters: { + const TIntermSequence& params = node->getSequence(); + for (TIntermSequence::const_iterator iter = params.begin(); + iter != params.end(); ++iter) + { + const TIntermTyped* param = (*iter)->getAsTyped(); + if (param->isArray()) + { + TQualifier qualifier = param->getQualifier(); + if ((qualifier == EvqOut) || (qualifier == EvqInOut)) + { + updateVersion(GLSL_VERSION_120); + break; + } + } + } + // Fully processed. No need to visit children. + visitChildren = false; + break; + } + case EOpConstructMat2: + case EOpConstructMat3: + case EOpConstructMat4: { + const TIntermSequence& sequence = node->getSequence(); + if (sequence.size() == 1) { + TIntermTyped* typed = sequence.front()->getAsTyped(); + if (typed && typed->isMatrix()) { + updateVersion(GLSL_VERSION_120); + } + } + break; + } + + default: break; + } + + return visitChildren; +} + +bool TVersionGLSL::visitLoop(Visit, TIntermLoop*) +{ + return true; +} + +bool TVersionGLSL::visitBranch(Visit, TIntermBranch*) +{ + return true; +} + +void TVersionGLSL::updateVersion(int version) +{ + mVersion = std::max(version, mVersion); +} + diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h new file mode 100644 index 0000000000..d310066171 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h @@ -0,0 +1,56 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_VERSIONGLSL_H_ +#define COMPILER_VERSIONGLSL_H_ + +#include "GLSLANG/ShaderLang.h" +#include "compiler/translator/intermediate.h" + +// Traverses the intermediate tree to return the minimum GLSL version +// required to legally access all built-in features used in the shader. +// GLSL 1.1 which is mandated by OpenGL 2.0 provides: +// - #version and #extension to declare version and extensions. +// - built-in functions refract, exp, and log. +// - updated step() to compare x < edge instead of x <= edge. +// GLSL 1.2 which is mandated by OpenGL 2.1 provides: +// - many changes to reduce differences when compared to the ES specification. +// - invariant keyword and its support. +// - c++ style name hiding rules. +// - built-in variable gl_PointCoord for fragment shaders. +// - matrix constructors taking matrix as argument. +// - array as "out" function parameters +// +class TVersionGLSL : public TIntermTraverser { +public: + TVersionGLSL(ShShaderType type); + + // Returns 120 if the following is used the shader: + // - "invariant", + // - "gl_PointCoord", + // - matrix/matrix constructors + // - array "out" parameters + // Else 110 is returned. + int getVersion() { return mVersion; } + + virtual void visitSymbol(TIntermSymbol*); + virtual void visitConstantUnion(TIntermConstantUnion*); + virtual bool visitBinary(Visit, TIntermBinary*); + virtual bool visitUnary(Visit, TIntermUnary*); + virtual bool visitSelection(Visit, TIntermSelection*); + virtual bool visitAggregate(Visit, TIntermAggregate*); + virtual bool visitLoop(Visit, TIntermLoop*); + virtual bool visitBranch(Visit, TIntermBranch*); + +protected: + void updateVersion(int version); + +private: + ShShaderType mShaderType; + int mVersion; +}; + +#endif // COMPILER_VERSIONGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/compilerdebug.cpp b/src/3rdparty/angle/src/compiler/translator/compilerdebug.cpp new file mode 100644 index 0000000000..10cbe43b8d --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/compilerdebug.cpp @@ -0,0 +1,37 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// debug.cpp: Debugging utilities. + +#include "compiler/translator/compilerdebug.h" + +#include +#include + +#include "compiler/translator/InitializeParseContext.h" +#include "compiler/translator/ParseContext.h" + +#ifdef TRACE_ENABLED +static const int kTraceBufferLen = 1024; + +extern "C" { +void Trace(const char *format, ...) { + if (!format) return; + + TParseContext* parseContext = GetGlobalParseContext(); + if (parseContext) { + char buf[kTraceBufferLen]; + va_list args; + va_start(args, format); + vsnprintf(buf, kTraceBufferLen, format, args); + va_end(args); + + parseContext->trace(buf); + } +} +} // extern "C" +#endif // TRACE_ENABLED + diff --git a/src/3rdparty/angle/src/compiler/translator/compilerdebug.h b/src/3rdparty/angle/src/compiler/translator/compilerdebug.h new file mode 100644 index 0000000000..7a371516af --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/compilerdebug.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// debug.h: Debugging utilities. + +#ifndef COMPILER_DEBUG_H_ +#define COMPILER_DEBUG_H_ + +#include + +#ifdef _DEBUG +#define TRACE_ENABLED // define to enable debug message tracing +#endif // _DEBUG + +// Outputs text to the debug log +#ifdef TRACE_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus +void Trace(const char* format, ...); +#ifdef __cplusplus +} +#endif // __cplusplus + +#else // TRACE_ENABLED + +#define Trace(...) ((void)0) + +#endif // TRACE_ENABLED + +// A macro asserting a condition and outputting failures to the debug log +#define ASSERT(expression) do { \ + if(!(expression)) \ + Trace("Assert failed: %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \ + assert(expression); \ +} while(0) + +#define UNIMPLEMENTED() do { \ + Trace("Unimplemented invoked: %s(%d)\n", __FUNCTION__, __LINE__); \ + assert(false); \ +} while(0) + +#define UNREACHABLE() do { \ + Trace("Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \ + assert(false); \ +} while(0) + +#endif // COMPILER_DEBUG_H_ + diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.cpp b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.cpp new file mode 100644 index 0000000000..19ddf5c439 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.cpp @@ -0,0 +1,97 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#pragma warning(disable: 4718) + +#include "compiler/translator/depgraph/DependencyGraph.h" +#include "compiler/translator/depgraph/DependencyGraphBuilder.h" + +TDependencyGraph::TDependencyGraph(TIntermNode* intermNode) +{ + TDependencyGraphBuilder::build(intermNode, this); +} + +TDependencyGraph::~TDependencyGraph() +{ + for (TGraphNodeVector::const_iterator iter = mAllNodes.begin(); iter != mAllNodes.end(); ++iter) + { + TGraphNode* node = *iter; + delete node; + } +} + +TGraphArgument* TDependencyGraph::createArgument(TIntermAggregate* intermFunctionCall, + int argumentNumber) +{ + TGraphArgument* argument = new TGraphArgument(intermFunctionCall, argumentNumber); + mAllNodes.push_back(argument); + return argument; +} + +TGraphFunctionCall* TDependencyGraph::createFunctionCall(TIntermAggregate* intermFunctionCall) +{ + TGraphFunctionCall* functionCall = new TGraphFunctionCall(intermFunctionCall); + mAllNodes.push_back(functionCall); + if (functionCall->getIntermFunctionCall()->isUserDefined()) + mUserDefinedFunctionCalls.push_back(functionCall); + return functionCall; +} + +TGraphSymbol* TDependencyGraph::getOrCreateSymbol(TIntermSymbol* intermSymbol) +{ + TSymbolIdMap::const_iterator iter = mSymbolIdMap.find(intermSymbol->getId()); + + TGraphSymbol* symbol = NULL; + + if (iter != mSymbolIdMap.end()) { + TSymbolIdPair pair = *iter; + symbol = pair.second; + } else { + symbol = new TGraphSymbol(intermSymbol); + mAllNodes.push_back(symbol); + + TSymbolIdPair pair(intermSymbol->getId(), symbol); + mSymbolIdMap.insert(pair); + + // We save all sampler symbols in a collection, so we can start graph traversals from them quickly. + if (IsSampler(intermSymbol->getBasicType())) + mSamplerSymbols.push_back(symbol); + } + + return symbol; +} + +TGraphSelection* TDependencyGraph::createSelection(TIntermSelection* intermSelection) +{ + TGraphSelection* selection = new TGraphSelection(intermSelection); + mAllNodes.push_back(selection); + return selection; +} + +TGraphLoop* TDependencyGraph::createLoop(TIntermLoop* intermLoop) +{ + TGraphLoop* loop = new TGraphLoop(intermLoop); + mAllNodes.push_back(loop); + return loop; +} + +TGraphLogicalOp* TDependencyGraph::createLogicalOp(TIntermBinary* intermLogicalOp) +{ + TGraphLogicalOp* logicalOp = new TGraphLogicalOp(intermLogicalOp); + mAllNodes.push_back(logicalOp); + return logicalOp; +} + +const char* TGraphLogicalOp::getOpString() const +{ + const char* opString = NULL; + switch (getIntermLogicalOp()->getOp()) { + case EOpLogicalAnd: opString = "and"; break; + case EOpLogicalOr: opString = "or"; break; + default: opString = "unknown"; break; + } + return opString; +} diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h new file mode 100644 index 0000000000..5ea1cbb837 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h @@ -0,0 +1,212 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H +#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H + +#include "compiler/translator/intermediate.h" + +#include +#include + +class TGraphNode; +class TGraphParentNode; +class TGraphArgument; +class TGraphFunctionCall; +class TGraphSymbol; +class TGraphSelection; +class TGraphLoop; +class TGraphLogicalOp; +class TDependencyGraphTraverser; +class TDependencyGraphOutput; + +typedef std::set TGraphNodeSet; +typedef std::vector TGraphNodeVector; +typedef std::vector TGraphSymbolVector; +typedef std::vector TFunctionCallVector; + +// +// Base class for all dependency graph nodes. +// +class TGraphNode { +public: + TGraphNode(TIntermNode* node) : intermNode(node) {} + virtual ~TGraphNode() {} + virtual void traverse(TDependencyGraphTraverser* graphTraverser); +protected: + TIntermNode* intermNode; +}; + +// +// Base class for dependency graph nodes that may have children. +// +class TGraphParentNode : public TGraphNode { +public: + TGraphParentNode(TIntermNode* node) : TGraphNode(node) {} + virtual ~TGraphParentNode() {} + void addDependentNode(TGraphNode* node) { if (node != this) mDependentNodes.insert(node); } + virtual void traverse(TDependencyGraphTraverser* graphTraverser); +private: + TGraphNodeSet mDependentNodes; +}; + +// +// Handle function call arguments. +// +class TGraphArgument : public TGraphParentNode { +public: + TGraphArgument(TIntermAggregate* intermFunctionCall, int argumentNumber) + : TGraphParentNode(intermFunctionCall) + , mArgumentNumber(argumentNumber) {} + virtual ~TGraphArgument() {} + const TIntermAggregate* getIntermFunctionCall() const { return intermNode->getAsAggregate(); } + int getArgumentNumber() const { return mArgumentNumber; } + virtual void traverse(TDependencyGraphTraverser* graphTraverser); +private: + int mArgumentNumber; +}; + +// +// Handle function calls. +// +class TGraphFunctionCall : public TGraphParentNode { +public: + TGraphFunctionCall(TIntermAggregate* intermFunctionCall) + : TGraphParentNode(intermFunctionCall) {} + virtual ~TGraphFunctionCall() {} + const TIntermAggregate* getIntermFunctionCall() const { return intermNode->getAsAggregate(); } + virtual void traverse(TDependencyGraphTraverser* graphTraverser); +}; + +// +// Handle symbols. +// +class TGraphSymbol : public TGraphParentNode { +public: + TGraphSymbol(TIntermSymbol* intermSymbol) : TGraphParentNode(intermSymbol) {} + virtual ~TGraphSymbol() {} + const TIntermSymbol* getIntermSymbol() const { return intermNode->getAsSymbolNode(); } + virtual void traverse(TDependencyGraphTraverser* graphTraverser); +}; + +// +// Handle if statements and ternary operators. +// +class TGraphSelection : public TGraphNode { +public: + TGraphSelection(TIntermSelection* intermSelection) : TGraphNode(intermSelection) {} + virtual ~TGraphSelection() {} + const TIntermSelection* getIntermSelection() const { return intermNode->getAsSelectionNode(); } + virtual void traverse(TDependencyGraphTraverser* graphTraverser); +}; + +// +// Handle for, do-while, and while loops. +// +class TGraphLoop : public TGraphNode { +public: + TGraphLoop(TIntermLoop* intermLoop) : TGraphNode(intermLoop) {} + virtual ~TGraphLoop() {} + const TIntermLoop* getIntermLoop() const { return intermNode->getAsLoopNode(); } + virtual void traverse(TDependencyGraphTraverser* graphTraverser); +}; + +// +// Handle logical and, or. +// +class TGraphLogicalOp : public TGraphNode { +public: + TGraphLogicalOp(TIntermBinary* intermLogicalOp) : TGraphNode(intermLogicalOp) {} + virtual ~TGraphLogicalOp() {} + const TIntermBinary* getIntermLogicalOp() const { return intermNode->getAsBinaryNode(); } + const char* getOpString() const; + virtual void traverse(TDependencyGraphTraverser* graphTraverser); +}; + +// +// A dependency graph of symbols, function calls, conditions etc. +// +// This class provides an interface to the entry points of the dependency graph. +// +// Dependency graph nodes should be created by using one of the provided "create..." methods. +// This class (and nobody else) manages the memory of the created nodes. +// Nodes may not be removed after being added, so all created nodes will exist while the +// TDependencyGraph instance exists. +// +class TDependencyGraph { +public: + TDependencyGraph(TIntermNode* intermNode); + ~TDependencyGraph(); + TGraphNodeVector::const_iterator begin() const { return mAllNodes.begin(); } + TGraphNodeVector::const_iterator end() const { return mAllNodes.end(); } + + TGraphSymbolVector::const_iterator beginSamplerSymbols() const + { + return mSamplerSymbols.begin(); + } + + TGraphSymbolVector::const_iterator endSamplerSymbols() const + { + return mSamplerSymbols.end(); + } + + TFunctionCallVector::const_iterator beginUserDefinedFunctionCalls() const + { + return mUserDefinedFunctionCalls.begin(); + } + + TFunctionCallVector::const_iterator endUserDefinedFunctionCalls() const + { + return mUserDefinedFunctionCalls.end(); + } + + TGraphArgument* createArgument(TIntermAggregate* intermFunctionCall, int argumentNumber); + TGraphFunctionCall* createFunctionCall(TIntermAggregate* intermFunctionCall); + TGraphSymbol* getOrCreateSymbol(TIntermSymbol* intermSymbol); + TGraphSelection* createSelection(TIntermSelection* intermSelection); + TGraphLoop* createLoop(TIntermLoop* intermLoop); + TGraphLogicalOp* createLogicalOp(TIntermBinary* intermLogicalOp); +private: + typedef TMap TSymbolIdMap; + typedef std::pair TSymbolIdPair; + + TGraphNodeVector mAllNodes; + TGraphSymbolVector mSamplerSymbols; + TFunctionCallVector mUserDefinedFunctionCalls; + TSymbolIdMap mSymbolIdMap; +}; + +// +// For traversing the dependency graph. Users should derive from this, +// put their traversal specific data in it, and then pass it to a +// traverse method. +// +// When using this, just fill in the methods for nodes you want visited. +// +class TDependencyGraphTraverser { +public: + TDependencyGraphTraverser() : mDepth(0) {} + + virtual void visitSymbol(TGraphSymbol* symbol) {}; + virtual void visitArgument(TGraphArgument* selection) {}; + virtual void visitFunctionCall(TGraphFunctionCall* functionCall) {}; + virtual void visitSelection(TGraphSelection* selection) {}; + virtual void visitLoop(TGraphLoop* loop) {}; + virtual void visitLogicalOp(TGraphLogicalOp* logicalOp) {}; + + int getDepth() const { return mDepth; } + void incrementDepth() { ++mDepth; } + void decrementDepth() { --mDepth; } + + void clearVisited() { mVisited.clear(); } + void markVisited(TGraphNode* node) { mVisited.insert(node); } + bool isVisited(TGraphNode* node) const { return mVisited.find(node) != mVisited.end(); } +private: + int mDepth; + TGraphNodeSet mVisited; +}; + +#endif diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp new file mode 100644 index 0000000000..d5f2cba5fc --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp @@ -0,0 +1,227 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/depgraph/DependencyGraphBuilder.h" + +void TDependencyGraphBuilder::build(TIntermNode* node, TDependencyGraph* graph) +{ + TDependencyGraphBuilder builder(graph); + builder.build(node); +} + +bool TDependencyGraphBuilder::visitAggregate(Visit visit, TIntermAggregate* intermAggregate) +{ + switch (intermAggregate->getOp()) { + case EOpFunction: visitFunctionDefinition(intermAggregate); break; + case EOpFunctionCall: visitFunctionCall(intermAggregate); break; + default: visitAggregateChildren(intermAggregate); break; + } + + return false; +} + +void TDependencyGraphBuilder::visitFunctionDefinition(TIntermAggregate* intermAggregate) +{ + // Currently, we do not support user defined functions. + if (intermAggregate->getName() != "main(") + return; + + visitAggregateChildren(intermAggregate); +} + +// Takes an expression like "f(x)" and creates a dependency graph like +// "x -> argument 0 -> function call". +void TDependencyGraphBuilder::visitFunctionCall(TIntermAggregate* intermFunctionCall) +{ + TGraphFunctionCall* functionCall = mGraph->createFunctionCall(intermFunctionCall); + + // Run through the function call arguments. + int argumentNumber = 0; + TIntermSequence& intermArguments = intermFunctionCall->getSequence(); + for (TIntermSequence::const_iterator iter = intermArguments.begin(); + iter != intermArguments.end(); + ++iter, ++argumentNumber) + { + TNodeSetMaintainer nodeSetMaintainer(this); + + TIntermNode* intermArgument = *iter; + intermArgument->traverse(this); + + if (TParentNodeSet* argumentNodes = mNodeSets.getTopSet()) { + TGraphArgument* argument = mGraph->createArgument(intermFunctionCall, argumentNumber); + connectMultipleNodesToSingleNode(argumentNodes, argument); + argument->addDependentNode(functionCall); + } + } + + // Push the leftmost symbol of this function call into the current set of dependent symbols to + // represent the result of this function call. + // Thus, an expression like "y = f(x)" will yield a dependency graph like + // "x -> argument 0 -> function call -> y". + // This line essentially passes the function call node back up to an earlier visitAssignment + // call, which will create the connection "function call -> y". + mNodeSets.insertIntoTopSet(functionCall); +} + +void TDependencyGraphBuilder::visitAggregateChildren(TIntermAggregate* intermAggregate) +{ + TIntermSequence& sequence = intermAggregate->getSequence(); + for(TIntermSequence::const_iterator iter = sequence.begin(); iter != sequence.end(); ++iter) + { + TIntermNode* intermChild = *iter; + intermChild->traverse(this); + } +} + +void TDependencyGraphBuilder::visitSymbol(TIntermSymbol* intermSymbol) +{ + // Push this symbol into the set of dependent symbols for the current assignment or condition + // that we are traversing. + TGraphSymbol* symbol = mGraph->getOrCreateSymbol(intermSymbol); + mNodeSets.insertIntoTopSet(symbol); + + // If this symbol is the current leftmost symbol under an assignment, replace the previous + // leftmost symbol with this symbol. + if (!mLeftmostSymbols.empty() && mLeftmostSymbols.top() != &mRightSubtree) { + mLeftmostSymbols.pop(); + mLeftmostSymbols.push(symbol); + } +} + +bool TDependencyGraphBuilder::visitBinary(Visit visit, TIntermBinary* intermBinary) +{ + TOperator op = intermBinary->getOp(); + if (op == EOpInitialize || intermBinary->isAssignment()) + visitAssignment(intermBinary); + else if (op == EOpLogicalAnd || op == EOpLogicalOr) + visitLogicalOp(intermBinary); + else + visitBinaryChildren(intermBinary); + + return false; +} + +void TDependencyGraphBuilder::visitAssignment(TIntermBinary* intermAssignment) +{ + TIntermTyped* intermLeft = intermAssignment->getLeft(); + if (!intermLeft) + return; + + TGraphSymbol* leftmostSymbol = NULL; + + { + TNodeSetMaintainer nodeSetMaintainer(this); + + { + TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mLeftSubtree); + intermLeft->traverse(this); + leftmostSymbol = mLeftmostSymbols.top(); + + // After traversing the left subtree of this assignment, we should have found a real + // leftmost symbol, and the leftmost symbol should not be a placeholder. + ASSERT(leftmostSymbol != &mLeftSubtree); + ASSERT(leftmostSymbol != &mRightSubtree); + } + + if (TIntermTyped* intermRight = intermAssignment->getRight()) { + TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree); + intermRight->traverse(this); + } + + if (TParentNodeSet* assignmentNodes = mNodeSets.getTopSet()) + connectMultipleNodesToSingleNode(assignmentNodes, leftmostSymbol); + } + + // Push the leftmost symbol of this assignment into the current set of dependent symbols to + // represent the result of this assignment. + // An expression like "a = (b = c)" will yield a dependency graph like "c -> b -> a". + // This line essentially passes the leftmost symbol of the nested assignment ("b" in this + // example) back up to the earlier visitAssignment call for the outer assignment, which will + // create the connection "b -> a". + mNodeSets.insertIntoTopSet(leftmostSymbol); +} + +void TDependencyGraphBuilder::visitLogicalOp(TIntermBinary* intermLogicalOp) +{ + if (TIntermTyped* intermLeft = intermLogicalOp->getLeft()) { + TNodeSetPropagatingMaintainer nodeSetMaintainer(this); + + intermLeft->traverse(this); + if (TParentNodeSet* leftNodes = mNodeSets.getTopSet()) { + TGraphLogicalOp* logicalOp = mGraph->createLogicalOp(intermLogicalOp); + connectMultipleNodesToSingleNode(leftNodes, logicalOp); + } + } + + if (TIntermTyped* intermRight = intermLogicalOp->getRight()) { + TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree); + intermRight->traverse(this); + } +} + +void TDependencyGraphBuilder::visitBinaryChildren(TIntermBinary* intermBinary) +{ + if (TIntermTyped* intermLeft = intermBinary->getLeft()) + intermLeft->traverse(this); + + if (TIntermTyped* intermRight = intermBinary->getRight()) { + TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree); + intermRight->traverse(this); + } +} + +bool TDependencyGraphBuilder::visitSelection(Visit visit, TIntermSelection* intermSelection) +{ + if (TIntermNode* intermCondition = intermSelection->getCondition()) { + TNodeSetMaintainer nodeSetMaintainer(this); + + intermCondition->traverse(this); + if (TParentNodeSet* conditionNodes = mNodeSets.getTopSet()) { + TGraphSelection* selection = mGraph->createSelection(intermSelection); + connectMultipleNodesToSingleNode(conditionNodes, selection); + } + } + + if (TIntermNode* intermTrueBlock = intermSelection->getTrueBlock()) + intermTrueBlock->traverse(this); + + if (TIntermNode* intermFalseBlock = intermSelection->getFalseBlock()) + intermFalseBlock->traverse(this); + + return false; +} + +bool TDependencyGraphBuilder::visitLoop(Visit visit, TIntermLoop* intermLoop) +{ + if (TIntermTyped* intermCondition = intermLoop->getCondition()) { + TNodeSetMaintainer nodeSetMaintainer(this); + + intermCondition->traverse(this); + if (TParentNodeSet* conditionNodes = mNodeSets.getTopSet()) { + TGraphLoop* loop = mGraph->createLoop(intermLoop); + connectMultipleNodesToSingleNode(conditionNodes, loop); + } + } + + if (TIntermNode* intermBody = intermLoop->getBody()) + intermBody->traverse(this); + + if (TIntermTyped* intermExpression = intermLoop->getExpression()) + intermExpression->traverse(this); + + return false; +} + + +void TDependencyGraphBuilder::connectMultipleNodesToSingleNode(TParentNodeSet* nodes, + TGraphNode* node) const +{ + for (TParentNodeSet::const_iterator iter = nodes->begin(); iter != nodes->end(); ++iter) + { + TGraphParentNode* currentNode = *iter; + currentNode->addDependentNode(node); + } +} diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h new file mode 100644 index 0000000000..3e928fb77e --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h @@ -0,0 +1,181 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H +#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H + +#include "compiler/translator/depgraph/DependencyGraph.h" + +// +// Creates a dependency graph of symbols, function calls, conditions etc. by traversing a +// intermediate tree. +// +class TDependencyGraphBuilder : public TIntermTraverser { +public: + static void build(TIntermNode* node, TDependencyGraph* graph); + + virtual void visitSymbol(TIntermSymbol*); + virtual bool visitBinary(Visit visit, TIntermBinary*); + virtual bool visitSelection(Visit visit, TIntermSelection*); + virtual bool visitAggregate(Visit visit, TIntermAggregate*); + virtual bool visitLoop(Visit visit, TIntermLoop*); + +private: + typedef std::stack TSymbolStack; + typedef std::set TParentNodeSet; + + // + // For collecting the dependent nodes of assignments, conditions, etc. + // while traversing the intermediate tree. + // + // This data structure is stack of sets. Each set contains dependency graph parent nodes. + // + class TNodeSetStack { + public: + TNodeSetStack() {}; + ~TNodeSetStack() { clear(); } + + // This should only be called after a pushSet. + // Returns NULL if the top set is empty. + TParentNodeSet* getTopSet() const + { + ASSERT(!nodeSets.empty()); + TParentNodeSet* topSet = nodeSets.top(); + return !topSet->empty() ? topSet : NULL; + } + + void pushSet() { nodeSets.push(new TParentNodeSet()); } + void popSet() + { + ASSERT(!nodeSets.empty()); + delete nodeSets.top(); + nodeSets.pop(); + } + + // Pops the top set and adds its contents to the new top set. + // This should only be called after a pushSet. + // If there is no set below the top set, the top set is just deleted. + void popSetIntoNext() + { + ASSERT(!nodeSets.empty()); + TParentNodeSet* oldTopSet = nodeSets.top(); + nodeSets.pop(); + + if (!nodeSets.empty()) { + TParentNodeSet* newTopSet = nodeSets.top(); + newTopSet->insert(oldTopSet->begin(), oldTopSet->end()); + } + + delete oldTopSet; + } + + // Does nothing if there is no top set. + // This can be called when there is no top set if we are visiting + // symbols that are not under an assignment or condition. + // We don't need to track those symbols. + void insertIntoTopSet(TGraphParentNode* node) + { + if (nodeSets.empty()) + return; + + nodeSets.top()->insert(node); + } + + void clear() + { + while (!nodeSets.empty()) + popSet(); + } + + private: + typedef std::stack TParentNodeSetStack; + + TParentNodeSetStack nodeSets; + }; + + // + // An instance of this class pushes a new node set when instantiated. + // When the instance goes out of scope, it and pops the node set. + // + class TNodeSetMaintainer { + public: + TNodeSetMaintainer(TDependencyGraphBuilder* factory) + : sets(factory->mNodeSets) { sets.pushSet(); } + ~TNodeSetMaintainer() { sets.popSet(); } + protected: + TNodeSetStack& sets; + }; + + // + // An instance of this class pushes a new node set when instantiated. + // When the instance goes out of scope, it and pops the top node set and adds its contents to + // the new top node set. + // + class TNodeSetPropagatingMaintainer { + public: + TNodeSetPropagatingMaintainer(TDependencyGraphBuilder* factory) + : sets(factory->mNodeSets) { sets.pushSet(); } + ~TNodeSetPropagatingMaintainer() { sets.popSetIntoNext(); } + protected: + TNodeSetStack& sets; + }; + + // + // An instance of this class keeps track of the leftmost symbol while we're exploring an + // assignment. + // It will push the placeholder symbol kLeftSubtree when instantiated under a left subtree, + // and kRightSubtree under a right subtree. + // When it goes out of scope, it will pop the leftmost symbol at the top of the scope. + // During traversal, the TDependencyGraphBuilder will replace kLeftSubtree with a real symbol. + // kRightSubtree will never be replaced by a real symbol because we are tracking the leftmost + // symbol. + // + class TLeftmostSymbolMaintainer { + public: + TLeftmostSymbolMaintainer(TDependencyGraphBuilder* factory, TGraphSymbol& subtree) + : leftmostSymbols(factory->mLeftmostSymbols) + { + needsPlaceholderSymbol = leftmostSymbols.empty() || leftmostSymbols.top() != &subtree; + if (needsPlaceholderSymbol) + leftmostSymbols.push(&subtree); + } + + ~TLeftmostSymbolMaintainer() + { + if (needsPlaceholderSymbol) + leftmostSymbols.pop(); + } + + protected: + TSymbolStack& leftmostSymbols; + bool needsPlaceholderSymbol; + }; + + TDependencyGraphBuilder(TDependencyGraph* graph) + : TIntermTraverser(true, false, false) + , mLeftSubtree(NULL) + , mRightSubtree(NULL) + , mGraph(graph) {} + void build(TIntermNode* intermNode) { intermNode->traverse(this); } + + void connectMultipleNodesToSingleNode(TParentNodeSet* nodes, TGraphNode* node) const; + + void visitAssignment(TIntermBinary*); + void visitLogicalOp(TIntermBinary*); + void visitBinaryChildren(TIntermBinary*); + void visitFunctionDefinition(TIntermAggregate*); + void visitFunctionCall(TIntermAggregate* intermFunctionCall); + void visitAggregateChildren(TIntermAggregate*); + + TGraphSymbol mLeftSubtree; + TGraphSymbol mRightSubtree; + + TDependencyGraph* mGraph; + TNodeSetStack mNodeSets; + TSymbolStack mLeftmostSymbols; +}; + +#endif // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp new file mode 100644 index 0000000000..e226333545 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp @@ -0,0 +1,65 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/depgraph/DependencyGraphOutput.h" + +void TDependencyGraphOutput::outputIndentation() +{ + for (int i = 0; i < getDepth(); ++i) + mSink << " "; +} + +void TDependencyGraphOutput::visitArgument(TGraphArgument* parameter) +{ + outputIndentation(); + mSink << "argument " << parameter->getArgumentNumber() << " of call to " + << parameter->getIntermFunctionCall()->getName() << "\n"; +} + +void TDependencyGraphOutput::visitFunctionCall(TGraphFunctionCall* functionCall) +{ + outputIndentation(); + mSink << "function call " << functionCall->getIntermFunctionCall()->getName() << "\n"; +} + +void TDependencyGraphOutput::visitSymbol(TGraphSymbol* symbol) +{ + outputIndentation(); + mSink << symbol->getIntermSymbol()->getSymbol() << " (symbol id: " + << symbol->getIntermSymbol()->getId() << ")\n"; +} + +void TDependencyGraphOutput::visitSelection(TGraphSelection* selection) +{ + outputIndentation(); + mSink << "selection\n"; +} + +void TDependencyGraphOutput::visitLoop(TGraphLoop* loop) +{ + outputIndentation(); + mSink << "loop condition\n"; +} + +void TDependencyGraphOutput::visitLogicalOp(TGraphLogicalOp* logicalOp) +{ + outputIndentation(); + mSink << "logical " << logicalOp->getOpString() << "\n"; +} + +void TDependencyGraphOutput::outputAllSpanningTrees(TDependencyGraph& graph) +{ + mSink << "\n"; + + for (TGraphNodeVector::const_iterator iter = graph.begin(); iter != graph.end(); ++iter) + { + TGraphNode* symbol = *iter; + mSink << "--- Dependency graph spanning tree ---\n"; + clearVisited(); + symbol->traverse(this); + mSink << "\n"; + } +} diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h new file mode 100644 index 0000000000..c3a4112278 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h @@ -0,0 +1,30 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H +#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H + +#include "compiler/translator/depgraph/DependencyGraph.h" +#include "compiler/translator/InfoSink.h" + +class TDependencyGraphOutput : public TDependencyGraphTraverser { +public: + TDependencyGraphOutput(TInfoSinkBase& sink) : mSink(sink) {} + virtual void visitSymbol(TGraphSymbol* symbol); + virtual void visitArgument(TGraphArgument* parameter); + virtual void visitFunctionCall(TGraphFunctionCall* functionCall); + virtual void visitSelection(TGraphSelection* selection); + virtual void visitLoop(TGraphLoop* loop); + virtual void visitLogicalOp(TGraphLogicalOp* logicalOp); + + void outputAllSpanningTrees(TDependencyGraph& graph); +private: + void outputIndentation(); + + TInfoSinkBase& mSink; +}; + +#endif // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp new file mode 100644 index 0000000000..197fde97e2 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp @@ -0,0 +1,69 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/depgraph/DependencyGraph.h" + +// These methods do a breadth-first traversal through the graph and mark visited nodes. + +void TGraphNode::traverse(TDependencyGraphTraverser* graphTraverser) +{ + graphTraverser->markVisited(this); +} + +void TGraphParentNode::traverse(TDependencyGraphTraverser* graphTraverser) +{ + TGraphNode::traverse(graphTraverser); + + graphTraverser->incrementDepth(); + + // Visit the parent node's children. + for (TGraphNodeSet::const_iterator iter = mDependentNodes.begin(); + iter != mDependentNodes.end(); + ++iter) + { + TGraphNode* node = *iter; + if (!graphTraverser->isVisited(node)) + node->traverse(graphTraverser); + } + + graphTraverser->decrementDepth(); +} + +void TGraphArgument::traverse(TDependencyGraphTraverser* graphTraverser) +{ + graphTraverser->visitArgument(this); + TGraphParentNode::traverse(graphTraverser); +} + +void TGraphFunctionCall::traverse(TDependencyGraphTraverser* graphTraverser) +{ + graphTraverser->visitFunctionCall(this); + TGraphParentNode::traverse(graphTraverser); +} + +void TGraphSymbol::traverse(TDependencyGraphTraverser* graphTraverser) +{ + graphTraverser->visitSymbol(this); + TGraphParentNode::traverse(graphTraverser); +} + +void TGraphSelection::traverse(TDependencyGraphTraverser* graphTraverser) +{ + graphTraverser->visitSelection(this); + TGraphNode::traverse(graphTraverser); +} + +void TGraphLoop::traverse(TDependencyGraphTraverser* graphTraverser) +{ + graphTraverser->visitLoop(this); + TGraphNode::traverse(graphTraverser); +} + +void TGraphLogicalOp::traverse(TDependencyGraphTraverser* graphTraverser) +{ + graphTraverser->visitLogicalOp(this); + TGraphNode::traverse(graphTraverser); +} diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.h b/src/3rdparty/angle/src/compiler/translator/glslang.h new file mode 100644 index 0000000000..f221199093 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/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 int glslang_scan(size_t count, + const char* const string[], + const int length[], + TParseContext* context); +extern int glslang_parse(TParseContext* context); + diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.l b/src/3rdparty/angle/src/compiler/translator/glslang.l new file mode 100644 index 0000000000..ffc1aa18ac --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/glslang.l @@ -0,0 +1,355 @@ +/* +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +This file contains the Lex specification for GLSL ES. +Based on ANSI C grammar, Lex specification: +http://www.lysator.liu.se/c/ANSI-C-grammar-l.html + +IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh, +WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). +*/ + +%top{ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// This file is auto-generated by generate_parser.sh. DO NOT EDIT! + +// Ignore errors in auto-generated code. +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wswitch-enum" +#elif defined(_MSC_VER) +#pragma warning(disable: 4065) +#pragma warning(disable: 4189) +#pragma warning(disable: 4505) +#pragma warning(disable: 4701) +#endif +} + +%{ +#include "compiler/translator/glslang.h" +#include "compiler/translator/ParseContext.h" +#include "compiler/preprocessor/Token.h" +#include "compiler/translator/util.h" +#include "glslang_tab.h" + +/* windows only pragma */ +#ifdef _MSC_VER +#pragma warning(disable : 4102) +#endif + +#define YY_USER_ACTION \ + yylloc->first_file = yylloc->last_file = yycolumn; \ + yylloc->first_line = yylloc->last_line = yylineno; + +#define YY_INPUT(buf, result, max_size) \ + result = string_input(buf, max_size, yyscanner); + +static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner); +static int check_type(yyscan_t yyscanner); +static int reserved_word(yyscan_t yyscanner); +static int int_constant(yyscan_t yyscanner); +static int float_constant(yyscan_t yyscanner); +%} + +%option noyywrap nounput never-interactive +%option yylineno reentrant bison-bridge bison-locations +%option extra-type="TParseContext*" + +D [0-9] +L [a-zA-Z_] +H [a-fA-F0-9] +E [Ee][+-]?{D}+ +O [0-7] + +%% + +"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" { return FLOAT_TYPE; } +"int" { return INT_TYPE; } +"void" { return VOID_TYPE; } +"bool" { return BOOL_TYPE; } +"true" { yylval->lex.b = true; return BOOLCONSTANT; } +"false" { yylval->lex.b = false; return BOOLCONSTANT; } + +"discard" { return DISCARD; } +"return" { return RETURN; } + +"mat2" { return MATRIX2; } +"mat3" { return MATRIX3; } +"mat4" { return MATRIX4; } + +"vec2" { return VEC2; } +"vec3" { return VEC3; } +"vec4" { return VEC4; } +"ivec2" { return IVEC2; } +"ivec3" { return IVEC3; } +"ivec4" { return IVEC4; } +"bvec2" { return BVEC2; } +"bvec3" { return BVEC3; } +"bvec4" { return BVEC4; } + +"sampler2D" { return SAMPLER2D; } +"samplerCube" { return SAMPLERCUBE; } +"samplerExternalOES" { return SAMPLER_EXTERNAL_OES; } +"sampler2DRect" { return SAMPLER2DRECT; } + +"struct" { return STRUCT; } + +"asm" { return reserved_word(yyscanner); } + +"class" { return reserved_word(yyscanner); } +"union" { return reserved_word(yyscanner); } +"enum" { return reserved_word(yyscanner); } +"typedef" { return reserved_word(yyscanner); } +"template" { return reserved_word(yyscanner); } +"this" { return reserved_word(yyscanner); } +"packed" { return reserved_word(yyscanner); } + +"goto" { return reserved_word(yyscanner); } +"switch" { return reserved_word(yyscanner); } +"default" { return reserved_word(yyscanner); } + +"inline" { return reserved_word(yyscanner); } +"noinline" { return reserved_word(yyscanner); } +"volatile" { return reserved_word(yyscanner); } +"public" { return reserved_word(yyscanner); } +"static" { return reserved_word(yyscanner); } +"extern" { return reserved_word(yyscanner); } +"external" { return reserved_word(yyscanner); } +"interface" { return reserved_word(yyscanner); } +"flat" { return reserved_word(yyscanner); } + +"long" { return reserved_word(yyscanner); } +"short" { return reserved_word(yyscanner); } +"double" { return reserved_word(yyscanner); } +"half" { return reserved_word(yyscanner); } +"fixed" { return reserved_word(yyscanner); } +"unsigned" { return reserved_word(yyscanner); } +"superp" { return reserved_word(yyscanner); } + +"input" { return reserved_word(yyscanner); } +"output" { return reserved_word(yyscanner); } + +"hvec2" { return reserved_word(yyscanner); } +"hvec3" { return reserved_word(yyscanner); } +"hvec4" { return reserved_word(yyscanner); } +"dvec2" { return reserved_word(yyscanner); } +"dvec3" { return reserved_word(yyscanner); } +"dvec4" { return reserved_word(yyscanner); } +"fvec2" { return reserved_word(yyscanner); } +"fvec3" { return reserved_word(yyscanner); } +"fvec4" { return reserved_word(yyscanner); } + +"sampler1D" { return reserved_word(yyscanner); } +"sampler3D" { return reserved_word(yyscanner); } +"sampler1DShadow" { return reserved_word(yyscanner); } +"sampler2DShadow" { return reserved_word(yyscanner); } +"sampler3DRect" { return reserved_word(yyscanner); } +"sampler2DRectShadow" { return reserved_word(yyscanner); } + +"sizeof" { return reserved_word(yyscanner); } +"cast" { return reserved_word(yyscanner); } + +"namespace" { return reserved_word(yyscanner); } +"using" { return reserved_word(yyscanner); } + +{L}({L}|{D})* { + yylval->lex.string = NewPoolTString(yytext); + return check_type(yyscanner); +} + +0[xX]{H}+ { return int_constant(yyscanner); } +0{O}+ { return int_constant(yyscanner); } +{D}+ { return int_constant(yyscanner); } + +{D}+{E} { return float_constant(yyscanner); } +{D}+"."{D}*({E})? { return float_constant(yyscanner); } +"."{D}+({E})? { return float_constant(yyscanner); } + +"+=" { 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; } +";" { return SEMICOLON; } +("{"|"<%") { return LEFT_BRACE; } +("}"|"%>") { return RIGHT_BRACE; } +"," { return COMMA; } +":" { return COLON; } +"=" { return EQUAL; } +"(" { return LEFT_PAREN; } +")" { return RIGHT_PAREN; } +("["|"<:") { return LEFT_BRACKET; } +("]"|":>") { return RIGHT_BRACKET; } +"." { return DOT; } +"!" { return BANG; } +"-" { return DASH; } +"~" { return TILDE; } +"+" { return PLUS; } +"*" { return STAR; } +"/" { return SLASH; } +"%" { return PERCENT; } +"<" { return LEFT_ANGLE; } +">" { return RIGHT_ANGLE; } +"|" { return VERTICAL_BAR; } +"^" { return CARET; } +"&" { return AMPERSAND; } +"?" { return QUESTION; } + +[ \t\v\n\f\r] { } +<> { yyterminate(); } +. { assert(false); return 0; } + +%% + +yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) { + pp::Token token; + yyget_extra(yyscanner)->preprocessor.lex(&token); + yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size(); + if (len < max_size) + memcpy(buf, token.text.c_str(), len); + yyset_column(token.location.file, yyscanner); + yyset_lineno(token.location.line, yyscanner); + + if (len >= max_size) + YY_FATAL_ERROR("Input buffer overflow"); + else if (len > 0) + buf[len++] = ' '; + return len; +} + +int check_type(yyscan_t yyscanner) { + struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; + + int token = IDENTIFIER; + TSymbol* symbol = yyextra->symbolTable.find(yytext); + if (symbol && symbol->isVariable()) { + TVariable* variable = static_cast(symbol); + if (variable->isUserType()) + 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(*yylloc, "Illegal use of reserved word", yytext, ""); + yyextra->recover(); + return 0; +} + +void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) { + context->error(*lloc, reason, yyget_text(context->scanner)); + context->recover(); +} + +int int_constant(yyscan_t yyscanner) { + struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; + + if (!atoi_clamp(yytext, &(yylval->lex.i))) + yyextra->warning(*yylloc, "Integer overflow", yytext, ""); + return INTCONSTANT; +} + +int float_constant(yyscan_t yyscanner) { + struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; + + if (!atof_clamp(yytext, &(yylval->lex.f))) + yyextra->warning(*yylloc, "Float overflow", yytext, ""); + return FLOATCONSTANT; +} + +int glslang_initialize(TParseContext* context) { + yyscan_t scanner = NULL; + if (yylex_init_extra(context, &scanner)) + return 1; + + context->scanner = scanner; + return 0; +} + +int glslang_finalize(TParseContext* context) { + yyscan_t scanner = context->scanner; + if (scanner == NULL) return 0; + + context->scanner = NULL; + yylex_destroy(scanner); + + return 0; +} + +int glslang_scan(size_t count, const char* const string[], const int length[], + TParseContext* context) { + yyrestart(NULL, context->scanner); + yyset_column(0, context->scanner); + yyset_lineno(1, context->scanner); + + // Initialize preprocessor. + if (!context->preprocessor.init(count, string, length)) + return 1; + context->preprocessor.setMaxTokenLength(SH_MAX_TOKEN_LENGTH); + + // Define extension macros. + const TExtensionBehavior& extBehavior = context->extensionBehavior(); + for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); + iter != extBehavior.end(); ++iter) { + context->preprocessor.predefineMacro(iter->first.c_str(), 1); + } + if (context->fragmentPrecisionHigh) + context->preprocessor.predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1); + + return 0; +} + diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.y b/src/3rdparty/angle/src/compiler/translator/glslang.y new file mode 100644 index 0000000000..7614ff3447 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/glslang.y @@ -0,0 +1,2014 @@ +/* +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +This file contains the Yacc grammar for GLSL ES. +Based on ANSI C Yacc grammar: +http://www.lysator.liu.se/c/ANSI-C-grammar-y.html + +IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh, +WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). +*/ + +%{ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// This file is auto-generated by generate_parser.sh. DO NOT EDIT! + +// Ignore errors in auto-generated code. +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wswitch-enum" +#elif defined(_MSC_VER) +#pragma warning(disable: 4065) +#pragma warning(disable: 4189) +#pragma warning(disable: 4505) +#pragma warning(disable: 4701) +#endif + +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/ParseContext.h" +#include "GLSLANG/ShaderLang.h" + +#define YYENABLE_NLS 0 + +#define YYLEX_PARAM context->scanner +%} + +%expect 1 /* One shift reduce conflict because of if | else */ +%pure-parser +%parse-param {TParseContext* context} +%locations + +%code requires { +#define YYLTYPE TSourceLoc +#define YYLTYPE_IS_DECLARED 1 +#define SH_MAX_TOKEN_LENGTH 256 // WebGL spec. +} + +%union { + struct { + union { + TString *string; + float f; + int i; + bool b; + }; + TSymbol* symbol; + } lex; + struct { + TOperator op; + union { + TIntermNode* intermNode; + TIntermNodePair nodePair; + TIntermTyped* intermTypedNode; + TIntermAggregate* intermAggregate; + }; + union { + TPublicType type; + TPrecision precision; + TQualifier qualifier; + TFunction* function; + TParameter param; + TField* field; + TFieldList* fieldList; + }; + } interm; +} + +%{ +extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner); +extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason); + +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + do { \ + if (YYID(N)) { \ + (Current).first_file = YYRHSLOC(Rhs, 1).first_file; \ + (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ + (Current).last_file = YYRHSLOC(Rhs, N).last_file; \ + (Current).last_line = YYRHSLOC(Rhs, N).last_line; \ + } \ + else { \ + (Current).first_file = YYRHSLOC(Rhs, 0).last_file; \ + (Current).first_line = YYRHSLOC(Rhs, 0).last_line; \ + (Current).last_file = YYRHSLOC(Rhs, 0).last_file; \ + (Current).last_line = YYRHSLOC(Rhs, 0).last_line; \ + } \ + } while (0) + +#define VERTEX_ONLY(S, L) { \ + if (context->shaderType != SH_VERTEX_SHADER) { \ + context->error(L, " supported in vertex shaders only ", S); \ + context->recover(); \ + } \ +} + +#define FRAG_ONLY(S, L) { \ + if (context->shaderType != SH_FRAGMENT_SHADER) { \ + context->error(L, " supported in fragment shaders only ", S); \ + context->recover(); \ + } \ +} +%} + +%token 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 +%token BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4 +%token MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING +%token STRUCT VOID_TYPE WHILE +%token SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT + +%token IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT +%token LEFT_OP RIGHT_OP +%token INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP +%token AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN +%token MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN +%token SUB_ASSIGN + +%token LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT +%token COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT +%token LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION + +%type identifier +%type assignment_operator unary_operator +%type variable_identifier primary_expression postfix_expression +%type expression integer_expression assignment_expression +%type unary_expression multiplicative_expression additive_expression +%type relational_expression equality_expression +%type conditional_expression constant_expression +%type logical_or_expression logical_xor_expression logical_and_expression +%type shift_expression and_expression exclusive_or_expression inclusive_or_expression +%type function_call initializer condition conditionopt + +%type translation_unit function_definition +%type statement simple_statement +%type statement_list compound_statement +%type declaration_statement selection_statement expression_statement +%type declaration external_declaration +%type for_init_statement compound_statement_no_new_scope +%type selection_rest_statement for_rest_statement +%type iteration_statement jump_statement statement_no_new_scope statement_with_scope +%type single_declaration init_declarator_list + +%type parameter_declaration parameter_declarator parameter_type_specifier +%type parameter_qualifier + +%type precision_qualifier +%type type_qualifier fully_specified_type type_specifier +%type type_specifier_no_prec type_specifier_nonarray +%type struct_specifier +%type struct_declarator +%type struct_declarator_list struct_declaration struct_declaration_list +%type function_header function_declarator function_identifier +%type function_header_with_parameters function_call_header +%type function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype +%type function_call_or_method + +%start translation_unit +%% + +identifier + : IDENTIFIER + | TYPE_NAME + +variable_identifier + : IDENTIFIER { + // The symbol table search was done in the lexical phase + const TSymbol *symbol = $1.symbol; + const TVariable *variable = 0; + + if (!symbol) + { + context->error(@1, "undeclared identifier", $1.string->c_str()); + context->recover(); + } + else if (!symbol->isVariable()) + { + context->error(@1, "variable expected", $1.string->c_str()); + context->recover(); + } + else + { + variable = static_cast(symbol); + + if (context->symbolTable.findBuiltIn(variable->getName()) && + !variable->getExtension().empty() && + context->extensionErrorCheck(@1, variable->getExtension())) + { + context->recover(); + } + } + + if (!variable) + { + TType type(EbtFloat, EbpUndefined); + TVariable *fakeVariable = new TVariable($1.string, type); + context->symbolTable.insert(*fakeVariable); + variable = fakeVariable; + } + + if (variable->getType().getQualifier() == EvqConst) + { + ConstantUnion* constArray = variable->getConstPointer(); + TType t(variable->getType()); + $$ = context->intermediate.addConstantUnion(constArray, t, @1); + } + else + { + $$ = context->intermediate.addSymbol(variable->getUniqueId(), + variable->getName(), + variable->getType(), + @1); + } + + // don't delete $1.string, it's used by error recovery, and the pool + // pop will reclaim the memory + } + ; + +primary_expression + : variable_identifier { + $$ = $1; + } + | INTCONSTANT { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst($1.i); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @1); + } + | FLOATCONSTANT { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setFConst($1.f); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1); + } + | BOOLCONSTANT { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst($1.b); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @1); + } + | LEFT_PAREN expression RIGHT_PAREN { + $$ = $2; + } + ; + +postfix_expression + : primary_expression { + $$ = $1; + } + | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET { + $$ = context->addIndexExpression($1, @2, $3); + } + | function_call { + $$ = $1; + } + | postfix_expression DOT identifier { + if ($1->isArray()) { + context->error(@3, "cannot apply dot operator to an array", "."); + context->recover(); + } + + if ($1->isVector()) { + TVectorFields fields; + if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, @3)) { + fields.num = 1; + fields.offsets[0] = 0; + context->recover(); + } + + if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields + $$ = context->addConstVectorNode(fields, $1, @3); + if ($$ == 0) { + context->recover(); + $$ = $1; + } + else + $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size())); + } else { + TString vectorString = *$3.string; + TIntermTyped* index = context->intermediate.addSwizzle(fields, @3); + $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, @2); + $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size())); + } + } else if ($1->isMatrix()) { + TMatrixFields fields; + if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, @3)) { + fields.wholeRow = false; + fields.wholeCol = false; + fields.row = 0; + fields.col = 0; + context->recover(); + } + + if (fields.wholeRow || fields.wholeCol) { + context->error(@2, " non-scalar fields not implemented yet", "."); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(0); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3); + $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2); + $$->setType(TType($1->getBasicType(), $1->getPrecision(),EvqTemporary, $1->getNominalSize())); + } else { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3); + $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2); + $$->setType(TType($1->getBasicType(), $1->getPrecision())); + } + } else if ($1->getBasicType() == EbtStruct) { + bool fieldFound = false; + const TFieldList& fields = $1->getType().getStruct()->fields(); + unsigned int i; + for (i = 0; i < fields.size(); ++i) { + if (fields[i]->name() == *$3.string) { + fieldFound = true; + break; + } + } + if (fieldFound) { + if ($1->getType().getQualifier() == EvqConst) { + $$ = context->addConstStruct(*$3.string, $1, @2); + if ($$ == 0) { + context->recover(); + $$ = $1; + } + else { + $$->setType(*fields[i]->type()); + // change the qualifier of the return type, not of the structure field + // as the structure definition is shared between various structures. + $$->getTypePointer()->setQualifier(EvqConst); + } + } else { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(i); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *fields[i]->type(), @3); + $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, @2); + $$->setType(*fields[i]->type()); + } + } else { + context->error(@2, " no such field in structure", $3.string->c_str()); + context->recover(); + $$ = $1; + } + } else { + context->error(@2, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str()); + context->recover(); + $$ = $1; + } + // don't delete $3.string, it's from the pool + } + | postfix_expression INC_OP { + if (context->lValueErrorCheck(@2, "++", $1)) + context->recover(); + $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, @2, context->symbolTable); + if ($$ == 0) { + context->unaryOpError(@2, "++", $1->getCompleteString()); + context->recover(); + $$ = $1; + } + } + | postfix_expression DEC_OP { + if (context->lValueErrorCheck(@2, "--", $1)) + context->recover(); + $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, @2, context->symbolTable); + if ($$ == 0) { + context->unaryOpError(@2, "--", $1->getCompleteString()); + context->recover(); + $$ = $1; + } + } + ; + +integer_expression + : expression { + if (context->integerErrorCheck($1, "[]")) + context->recover(); + $$ = $1; + } + ; + +function_call + : function_call_or_method { + TFunction* fnCall = $1.function; + TOperator op = fnCall->getBuiltInOp(); + + if (op != EOpNull) + { + // + // Then this should be a constructor. + // Don't go through the symbol table for constructors. + // Their parameters will be verified algorithmically. + // + TType type(EbtVoid, EbpUndefined); // use this to get the type back + if (context->constructorErrorCheck(@1, $1.intermNode, *fnCall, op, &type)) { + $$ = 0; + } else { + // + // It's a constructor, of type 'type'. + // + $$ = context->addConstructor($1.intermNode, &type, op, fnCall, @1); + } + + if ($$ == 0) { + context->recover(); + $$ = context->intermediate.setAggregateOperator(0, op, @1); + } + $$->setType(type); + } else { + // + // Not a constructor. Find it in the symbol table. + // + const TFunction* fnCandidate; + bool builtIn; + fnCandidate = context->findFunction(@1, fnCall, &builtIn); + if (fnCandidate) { + // + // A declared function. + // + if (builtIn && !fnCandidate->getExtension().empty() && + context->extensionErrorCheck(@1, fnCandidate->getExtension())) { + context->recover(); + } + op = fnCandidate->getBuiltInOp(); + if (builtIn && op != EOpNull) { + // + // A function call mapped to a built-in operation. + // + if (fnCandidate->getParamCount() == 1) { + // + // Treat it like a built-in unary operator. + // + $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1, context->symbolTable); + if ($$ == 0) { + std::stringstream extraInfoStream; + extraInfoStream << "built in unary operator function. Type: " << static_cast($1.intermNode)->getCompleteString(); + std::string extraInfo = extraInfoStream.str(); + context->error($1.intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str()); + YYERROR; + } + } else { + $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1); + } + } else { + // This is a real function call + + $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1); + $$->setType(fnCandidate->getReturnType()); + + // this is how we know whether the given function is a builtIn function or a user defined function + // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also + // if builtIn == true, it's definitely a builtIn function with EOpNull + if (!builtIn) + $$->getAsAggregate()->setUserDefined(); + $$->getAsAggregate()->setName(fnCandidate->getMangledName()); + + TQualifier qual; + for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) { + qual = fnCandidate->getParam(i).type->getQualifier(); + if (qual == EvqOut || qual == EvqInOut) { + if (context->lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) { + context->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error"); + context->recover(); + } + } + } + } + $$->setType(fnCandidate->getReturnType()); + } else { + // error message was put out by PaFindFunction() + // Put on a dummy node for error recovery + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setFConst(0.0f); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1); + context->recover(); + } + } + delete fnCall; + } + ; + +function_call_or_method + : function_call_generic { + $$ = $1; + } + | postfix_expression DOT function_call_generic { + context->error(@3, "methods are not supported", ""); + context->recover(); + $$ = $3; + } + ; + +function_call_generic + : function_call_header_with_parameters RIGHT_PAREN { + $$ = $1; + } + | function_call_header_no_parameters RIGHT_PAREN { + $$ = $1; + } + ; + +function_call_header_no_parameters + : function_call_header VOID_TYPE { + $$.function = $1; + $$.intermNode = 0; + } + | function_call_header { + $$.function = $1; + $$.intermNode = 0; + } + ; + +function_call_header_with_parameters + : function_call_header assignment_expression { + TParameter param = { 0, new TType($2->getType()) }; + $1->addParameter(param); + $$.function = $1; + $$.intermNode = $2; + } + | function_call_header_with_parameters COMMA assignment_expression { + TParameter param = { 0, new TType($3->getType()) }; + $1.function->addParameter(param); + $$.function = $1.function; + $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, @2); + } + ; + +function_call_header + : function_identifier LEFT_PAREN { + $$ = $1; + } + ; + +// Grammar Note: Constructors look like functions, but are recognized as types. + +function_identifier + : type_specifier_nonarray { + // + // Constructor + // + TOperator op = EOpNull; + if ($1.userDef) { + op = EOpConstructStruct; + } else { + switch ($1.type) { + case EbtFloat: + if ($1.matrix) { + switch($1.size) { + case 2: op = EOpConstructMat2; break; + case 3: op = EOpConstructMat3; break; + case 4: op = EOpConstructMat4; break; + } + } else { + switch($1.size) { + case 1: op = EOpConstructFloat; break; + case 2: op = EOpConstructVec2; break; + case 3: op = EOpConstructVec3; break; + case 4: op = EOpConstructVec4; break; + } + } + break; + case EbtInt: + switch($1.size) { + case 1: op = EOpConstructInt; break; + case 2: op = EOpConstructIVec2; break; + case 3: op = EOpConstructIVec3; break; + case 4: op = EOpConstructIVec4; break; + } + break; + case EbtBool: + switch($1.size) { + case 1: op = EOpConstructBool; break; + case 2: op = EOpConstructBVec2; break; + case 3: op = EOpConstructBVec3; break; + case 4: op = EOpConstructBVec4; break; + } + break; + default: break; + } + if (op == EOpNull) { + context->error(@1, "cannot construct this type", getBasicString($1.type)); + context->recover(); + $1.type = EbtFloat; + op = EOpConstructFloat; + } + } + TString tempString; + TType type($1); + TFunction *function = new TFunction(&tempString, type, op); + $$ = function; + } + | IDENTIFIER { + if (context->reservedErrorCheck(@1, *$1.string)) + context->recover(); + TType type(EbtVoid, EbpUndefined); + TFunction *function = new TFunction($1.string, type); + $$ = function; + } + ; + +unary_expression + : postfix_expression { + $$ = $1; + } + | INC_OP unary_expression { + if (context->lValueErrorCheck(@1, "++", $2)) + context->recover(); + $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, @1, context->symbolTable); + if ($$ == 0) { + context->unaryOpError(@1, "++", $2->getCompleteString()); + context->recover(); + $$ = $2; + } + } + | DEC_OP unary_expression { + if (context->lValueErrorCheck(@1, "--", $2)) + context->recover(); + $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, @1, context->symbolTable); + if ($$ == 0) { + context->unaryOpError(@1, "--", $2->getCompleteString()); + context->recover(); + $$ = $2; + } + } + | unary_operator unary_expression { + if ($1.op != EOpNull) { + $$ = context->intermediate.addUnaryMath($1.op, $2, @1, context->symbolTable); + if ($$ == 0) { + const char* errorOp = ""; + switch($1.op) { + case EOpNegative: errorOp = "-"; break; + case EOpLogicalNot: errorOp = "!"; break; + default: break; + } + context->unaryOpError(@1, errorOp, $2->getCompleteString()); + context->recover(); + $$ = $2; + } + } else + $$ = $2; + } + ; +// Grammar Note: No traditional style type casts. + +unary_operator + : PLUS { $$.op = EOpNull; } + | DASH { $$.op = EOpNegative; } + | BANG { $$.op = EOpLogicalNot; } + ; +// Grammar Note: No '*' or '&' unary ops. Pointers are not supported. + +multiplicative_expression + : unary_expression { $$ = $1; } + | multiplicative_expression STAR unary_expression { + $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, @2, context->symbolTable); + if ($$ == 0) { + context->binaryOpError(@2, "*", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + $$ = $1; + } + } + | multiplicative_expression SLASH unary_expression { + $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, @2, context->symbolTable); + if ($$ == 0) { + context->binaryOpError(@2, "/", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + $$ = $1; + } + } + ; + +additive_expression + : multiplicative_expression { $$ = $1; } + | additive_expression PLUS multiplicative_expression { + $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, @2, context->symbolTable); + if ($$ == 0) { + context->binaryOpError(@2, "+", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + $$ = $1; + } + } + | additive_expression DASH multiplicative_expression { + $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, @2, context->symbolTable); + if ($$ == 0) { + context->binaryOpError(@2, "-", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + $$ = $1; + } + } + ; + +shift_expression + : additive_expression { $$ = $1; } + ; + +relational_expression + : shift_expression { $$ = $1; } + | relational_expression LEFT_ANGLE shift_expression { + $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, @2, context->symbolTable); + if ($$ == 0) { + context->binaryOpError(@2, "<", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); + } + } + | relational_expression RIGHT_ANGLE shift_expression { + $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, @2, context->symbolTable); + if ($$ == 0) { + context->binaryOpError(@2, ">", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); + } + } + | relational_expression LE_OP shift_expression { + $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, @2, context->symbolTable); + if ($$ == 0) { + context->binaryOpError(@2, "<=", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); + } + } + | relational_expression GE_OP shift_expression { + $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, @2, context->symbolTable); + if ($$ == 0) { + context->binaryOpError(@2, ">=", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); + } + } + ; + +equality_expression + : relational_expression { $$ = $1; } + | equality_expression EQ_OP relational_expression { + $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, @2, context->symbolTable); + if ($$ == 0) { + context->binaryOpError(@2, "==", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); + } + } + | equality_expression NE_OP relational_expression { + $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, @2, context->symbolTable); + if ($$ == 0) { + context->binaryOpError(@2, "!=", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); + } + } + ; + +and_expression + : equality_expression { $$ = $1; } + ; + +exclusive_or_expression + : and_expression { $$ = $1; } + ; + +inclusive_or_expression + : exclusive_or_expression { $$ = $1; } + ; + +logical_and_expression + : inclusive_or_expression { $$ = $1; } + | logical_and_expression AND_OP inclusive_or_expression { + $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, @2, context->symbolTable); + if ($$ == 0) { + context->binaryOpError(@2, "&&", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); + } + } + ; + +logical_xor_expression + : logical_and_expression { $$ = $1; } + | logical_xor_expression XOR_OP logical_and_expression { + $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, @2, context->symbolTable); + if ($$ == 0) { + context->binaryOpError(@2, "^^", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); + } + } + ; + +logical_or_expression + : logical_xor_expression { $$ = $1; } + | logical_or_expression OR_OP logical_xor_expression { + $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, @2, context->symbolTable); + if ($$ == 0) { + context->binaryOpError(@2, "||", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); + } + } + ; + +conditional_expression + : logical_or_expression { $$ = $1; } + | logical_or_expression QUESTION expression COLON assignment_expression { + if (context->boolErrorCheck(@2, $1)) + context->recover(); + + $$ = context->intermediate.addSelection($1, $3, $5, @2); + if ($3->getType() != $5->getType()) + $$ = 0; + + if ($$ == 0) { + context->binaryOpError(@2, ":", $3->getCompleteString(), $5->getCompleteString()); + context->recover(); + $$ = $5; + } + } + ; + +assignment_expression + : conditional_expression { $$ = $1; } + | unary_expression assignment_operator assignment_expression { + if (context->lValueErrorCheck(@2, "assign", $1)) + context->recover(); + $$ = context->intermediate.addAssign($2.op, $1, $3, @2); + if ($$ == 0) { + context->assignError(@2, "assign", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + $$ = $1; + } + } + ; + +assignment_operator + : EQUAL { $$.op = EOpAssign; } + | MUL_ASSIGN { $$.op = EOpMulAssign; } + | DIV_ASSIGN { $$.op = EOpDivAssign; } + | ADD_ASSIGN { $$.op = EOpAddAssign; } + | SUB_ASSIGN { $$.op = EOpSubAssign; } + ; + +expression + : assignment_expression { + $$ = $1; + } + | expression COMMA assignment_expression { + $$ = context->intermediate.addComma($1, $3, @2); + if ($$ == 0) { + context->binaryOpError(@2, ",", $1->getCompleteString(), $3->getCompleteString()); + context->recover(); + $$ = $3; + } + } + ; + +constant_expression + : conditional_expression { + if (context->constErrorCheck($1)) + context->recover(); + $$ = $1; + } + ; + +declaration + : function_prototype SEMICOLON { + TFunction &function = *($1.function); + + TIntermAggregate *prototype = new TIntermAggregate; + prototype->setType(function.getReturnType()); + prototype->setName(function.getName()); + + for (size_t i = 0; i < function.getParamCount(); i++) + { + const TParameter ¶m = function.getParam(i); + if (param.name != 0) + { + TVariable variable(param.name, *param.type); + + prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), @1), @1); + } + else + { + prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, @1), @1); + } + } + + prototype->setOp(EOpPrototype); + $$ = prototype; + + context->symbolTable.pop(); + } + | init_declarator_list SEMICOLON { + if ($1.intermAggregate) + $1.intermAggregate->setOp(EOpDeclaration); + $$ = $1.intermAggregate; + } + | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON { + if (($2 == EbpHigh) && (context->shaderType == SH_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) { + context->error(@1, "precision is not supported in fragment shader", "highp"); + context->recover(); + } + if (!context->symbolTable.setDefaultPrecision( $3, $2 )) { + context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.type)); + context->recover(); + } + $$ = 0; + } + ; + +function_prototype + : function_declarator RIGHT_PAREN { + // + // Multiple declarations of the same function are allowed. + // + // If this is a definition, the definition production code will check for redefinitions + // (we don't know at this point if it's a definition or not). + // + // Redeclarations are allowed. But, return types and parameter qualifiers must match. + // + TFunction* prevDec = static_cast(context->symbolTable.find($1->getMangledName())); + if (prevDec) { + if (prevDec->getReturnType() != $1->getReturnType()) { + context->error(@2, "overloaded functions must have the same return type", $1->getReturnType().getBasicString()); + context->recover(); + } + for (size_t i = 0; i < prevDec->getParamCount(); ++i) { + if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) { + context->error(@2, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString()); + context->recover(); + } + } + } + + // + // Check for previously declared variables using the same name. + // + TSymbol *prevSym = context->symbolTable.find($1->getName()); + if (prevSym) + { + if (!prevSym->isFunction()) + { + context->error(@2, "redefinition", $1->getName().c_str(), "function"); + context->recover(); + } + } + else + { + // Insert the unmangled name to detect potential future redefinition as a variable. + context->symbolTable.getOuterLevel()->insert($1->getName(), *$1); + } + + // + // If this is a redeclaration, it could also be a definition, + // in which case, we want to use the variable names from this one, and not the one that's + // being redeclared. So, pass back up this declaration, not the one in the symbol table. + // + $$.function = $1; + + // We're at the inner scope level of the function's arguments and body statement. + // Add the function prototype to the surrounding scope instead. + context->symbolTable.getOuterLevel()->insert(*$$.function); + } + ; + +function_declarator + : function_header { + $$ = $1; + } + | function_header_with_parameters { + $$ = $1; + } + ; + + +function_header_with_parameters + : function_header parameter_declaration { + // Add the parameter + $$ = $1; + if ($2.param.type->getBasicType() != EbtVoid) + $1->addParameter($2.param); + else + delete $2.param.type; + } + | function_header_with_parameters COMMA parameter_declaration { + // + // Only first parameter of one-parameter functions can be void + // The check for named parameters not being void is done in parameter_declarator + // + if ($3.param.type->getBasicType() == EbtVoid) { + // + // This parameter > first is void + // + context->error(@2, "cannot be an argument type except for '(void)'", "void"); + context->recover(); + delete $3.param.type; + } else { + // Add the parameter + $$ = $1; + $1->addParameter($3.param); + } + } + ; + +function_header + : fully_specified_type IDENTIFIER LEFT_PAREN { + if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) { + context->error(@2, "no qualifiers allowed for function return", getQualifierString($1.qualifier)); + context->recover(); + } + // make sure a sampler is not involved as well... + if (context->structQualifierErrorCheck(@2, $1)) + context->recover(); + + // Add the function as a prototype after parsing it (we do not support recursion) + TFunction *function; + TType type($1); + function = new TFunction($2.string, type); + $$ = function; + + context->symbolTable.push(); + } + ; + +parameter_declarator + // Type + name + : type_specifier identifier { + if ($1.type == EbtVoid) { + context->error(@2, "illegal use of type 'void'", $2.string->c_str()); + context->recover(); + } + if (context->reservedErrorCheck(@2, *$2.string)) + context->recover(); + TParameter param = {$2.string, new TType($1)}; + $$.param = param; + } + | type_specifier identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { + // Check that we can make an array out of this type + if (context->arrayTypeErrorCheck(@3, $1)) + context->recover(); + + if (context->reservedErrorCheck(@2, *$2.string)) + context->recover(); + + int size; + if (context->arraySizeErrorCheck(@3, $4, size)) + context->recover(); + $1.setArray(true, size); + + TType* type = new TType($1); + TParameter param = { $2.string, type }; + $$.param = param; + } + ; + +parameter_declaration + // + // The only parameter qualifier a parameter can have are + // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST. + // + + // + // Type + name + // + : type_qualifier parameter_qualifier parameter_declarator { + $$ = $3; + if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type)) + context->recover(); + } + | parameter_qualifier parameter_declarator { + $$ = $2; + if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type)) + context->recover(); + if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type)) + context->recover(); + } + // + // Only type + // + | type_qualifier parameter_qualifier parameter_type_specifier { + $$ = $3; + if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type)) + context->recover(); + } + | parameter_qualifier parameter_type_specifier { + $$ = $2; + if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type)) + context->recover(); + if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type)) + context->recover(); + } + ; + +parameter_qualifier + : /* empty */ { + $$ = EvqIn; + } + | IN_QUAL { + $$ = EvqIn; + } + | OUT_QUAL { + $$ = EvqOut; + } + | INOUT_QUAL { + $$ = EvqInOut; + } + ; + +parameter_type_specifier + : type_specifier { + TParameter param = { 0, new TType($1) }; + $$.param = param; + } + ; + +init_declarator_list + : single_declaration { + $$ = $1; + } + | init_declarator_list COMMA identifier { + if ($1.type.type == EbtInvariant && !$3.symbol) + { + context->error(@3, "undeclared identifier declared as invariant", $3.string->c_str()); + context->recover(); + } + + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), @3); + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, @3); + + if (context->structQualifierErrorCheck(@3, $$.type)) + context->recover(); + + if (context->nonInitConstErrorCheck(@3, *$3.string, $$.type, false)) + context->recover(); + + TVariable* variable = 0; + if (context->nonInitErrorCheck(@3, *$3.string, $$.type, variable)) + context->recover(); + if (symbol && variable) + symbol->setId(variable->getUniqueId()); + } + | init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET { + if (context->structQualifierErrorCheck(@3, $1.type)) + context->recover(); + + if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true)) + context->recover(); + + $$ = $1; + + if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type)) + context->recover(); + else { + $1.type.setArray(true); + TVariable* variable; + if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable)) + context->recover(); + } + } + | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { + if (context->structQualifierErrorCheck(@3, $1.type)) + context->recover(); + + if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true)) + context->recover(); + + $$ = $1; + + if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type)) + context->recover(); + else { + int size; + if (context->arraySizeErrorCheck(@4, $5, size)) + context->recover(); + $1.type.setArray(true, size); + TVariable* variable = 0; + if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable)) + context->recover(); + TType type = TType($1.type); + type.setArraySize(size); + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, @3), @3); + } + } + | init_declarator_list COMMA identifier EQUAL initializer { + if (context->structQualifierErrorCheck(@3, $1.type)) + context->recover(); + + $$ = $1; + + TIntermNode* intermNode; + if (!context->executeInitializer(@3, *$3.string, $1.type, $5, intermNode)) { + // + // build the intermediate representation + // + if (intermNode) + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, @4); + else + $$.intermAggregate = $1.intermAggregate; + } else { + context->recover(); + $$.intermAggregate = 0; + } + } + ; + +single_declaration + : fully_specified_type { + $$.type = $1; + $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), @1), @1); + } + | fully_specified_type identifier { + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); + + if (context->structQualifierErrorCheck(@2, $$.type)) + context->recover(); + + if (context->nonInitConstErrorCheck(@2, *$2.string, $$.type, false)) + context->recover(); + + $$.type = $1; + + TVariable* variable = 0; + if (context->nonInitErrorCheck(@2, *$2.string, $$.type, variable)) + context->recover(); + if (variable && symbol) + symbol->setId(variable->getUniqueId()); + } + | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET { + context->error(@2, "unsized array declarations not supported", $2.string->c_str()); + context->recover(); + + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); + $$.type = $1; + } + | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { + TType type = TType($1); + int size; + if (context->arraySizeErrorCheck(@2, $4, size)) + context->recover(); + type.setArraySize(size); + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, @2); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); + + if (context->structQualifierErrorCheck(@2, $1)) + context->recover(); + + if (context->nonInitConstErrorCheck(@2, *$2.string, $1, true)) + context->recover(); + + $$.type = $1; + + if (context->arrayTypeErrorCheck(@3, $1) || context->arrayQualifierErrorCheck(@3, $1)) + context->recover(); + else { + int size; + if (context->arraySizeErrorCheck(@3, $4, size)) + context->recover(); + + $1.setArray(true, size); + TVariable* variable = 0; + if (context->arrayErrorCheck(@3, *$2.string, $1, variable)) + context->recover(); + if (variable && symbol) + symbol->setId(variable->getUniqueId()); + } + } + | fully_specified_type identifier EQUAL initializer { + if (context->structQualifierErrorCheck(@2, $1)) + context->recover(); + + $$.type = $1; + + TIntermNode* intermNode; + if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode)) { + // + // Build intermediate representation + // + if(intermNode) + $$.intermAggregate = context->intermediate.makeAggregate(intermNode, @3); + else + $$.intermAggregate = 0; + } else { + context->recover(); + $$.intermAggregate = 0; + } + } + | INVARIANT IDENTIFIER { + VERTEX_ONLY("invariant declaration", @1); + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying")) + context->recover(); + $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, @2); + if (!$2.symbol) + { + context->error(@2, "undeclared identifier declared as invariant", $2.string->c_str()); + context->recover(); + + $$.intermAggregate = 0; + } + else + { + TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), @2); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); + } + } + ; + +fully_specified_type + : type_specifier { + $$ = $1; + + if ($1.array) { + context->error(@1, "not supported", "first-class array"); + context->recover(); + $1.setArray(false); + } + } + | type_qualifier type_specifier { + if ($2.array) { + context->error(@2, "not supported", "first-class array"); + context->recover(); + $2.setArray(false); + } + + if ($1.qualifier == EvqAttribute && + ($2.type == EbtBool || $2.type == EbtInt)) { + context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier)); + context->recover(); + } + if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) && + ($2.type == EbtBool || $2.type == EbtInt)) { + context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier)); + context->recover(); + } + $$ = $2; + $$.qualifier = $1.qualifier; + } + ; + +type_qualifier + : CONST_QUAL { + $$.setBasic(EbtVoid, EvqConst, @1); + } + | ATTRIBUTE { + VERTEX_ONLY("attribute", @1); + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "attribute")) + context->recover(); + $$.setBasic(EbtVoid, EvqAttribute, @1); + } + | VARYING { + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "varying")) + context->recover(); + if (context->shaderType == SH_VERTEX_SHADER) + $$.setBasic(EbtVoid, EvqVaryingOut, @1); + else + $$.setBasic(EbtVoid, EvqVaryingIn, @1); + } + | INVARIANT VARYING { + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying")) + context->recover(); + if (context->shaderType == SH_VERTEX_SHADER) + $$.setBasic(EbtVoid, EvqInvariantVaryingOut, @1); + else + $$.setBasic(EbtVoid, EvqInvariantVaryingIn, @1); + } + | UNIFORM { + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "uniform")) + context->recover(); + $$.setBasic(EbtVoid, EvqUniform, @1); + } + ; + +type_specifier + : type_specifier_no_prec { + $$ = $1; + + if ($$.precision == EbpUndefined) { + $$.precision = context->symbolTable.getDefaultPrecision($1.type); + if (context->precisionErrorCheck(@1, $$.precision, $1.type)) { + context->recover(); + } + } + } + | precision_qualifier type_specifier_no_prec { + $$ = $2; + $$.precision = $1; + } + ; + +precision_qualifier + : HIGH_PRECISION { + $$ = EbpHigh; + } + | MEDIUM_PRECISION { + $$ = EbpMedium; + } + | LOW_PRECISION { + $$ = EbpLow; + } + ; + +type_specifier_no_prec + : type_specifier_nonarray { + $$ = $1; + } + | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET { + $$ = $1; + + if (context->arrayTypeErrorCheck(@2, $1)) + context->recover(); + else { + int size; + if (context->arraySizeErrorCheck(@2, $3, size)) + context->recover(); + $$.setArray(true, size); + } + } + ; + +type_specifier_nonarray + : VOID_TYPE { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtVoid, qual, @1); + } + | FLOAT_TYPE { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); + } + | INT_TYPE { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtInt, qual, @1); + } + | BOOL_TYPE { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtBool, qual, @1); + } + | VEC2 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); + $$.setAggregate(2); + } + | VEC3 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); + $$.setAggregate(3); + } + | VEC4 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); + $$.setAggregate(4); + } + | BVEC2 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtBool, qual, @1); + $$.setAggregate(2); + } + | BVEC3 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtBool, qual, @1); + $$.setAggregate(3); + } + | BVEC4 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtBool, qual, @1); + $$.setAggregate(4); + } + | IVEC2 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtInt, qual, @1); + $$.setAggregate(2); + } + | IVEC3 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtInt, qual, @1); + $$.setAggregate(3); + } + | IVEC4 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtInt, qual, @1); + $$.setAggregate(4); + } + | MATRIX2 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); + $$.setAggregate(2, true); + } + | MATRIX3 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); + $$.setAggregate(3, true); + } + | MATRIX4 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); + $$.setAggregate(4, true); + } + | SAMPLER2D { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler2D, qual, @1); + } + | SAMPLERCUBE { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSamplerCube, qual, @1); + } + | SAMPLER_EXTERNAL_OES { + if (!context->supportsExtension("GL_OES_EGL_image_external")) { + context->error(@1, "unsupported type", "samplerExternalOES"); + context->recover(); + } + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSamplerExternalOES, qual, @1); + } + | SAMPLER2DRECT { + if (!context->supportsExtension("GL_ARB_texture_rectangle")) { + context->error(@1, "unsupported type", "sampler2DRect"); + context->recover(); + } + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler2DRect, qual, @1); + } + | struct_specifier { + $$ = $1; + $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + } + | TYPE_NAME { + // + // This is for user defined type names. The lexical phase looked up the + // type. + // + TType& structure = static_cast($1.symbol)->getType(); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtStruct, qual, @1); + $$.userDef = &structure; + } + ; + +struct_specifier + : STRUCT identifier LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { + if (context->reservedErrorCheck(@2, *$2.string)) + context->recover(); + + TType* structure = new TType(new TStructure($2.string, $5)); + TVariable* userTypeDef = new TVariable($2.string, *structure, true); + if (! context->symbolTable.insert(*userTypeDef)) { + context->error(@2, "redefinition", $2.string->c_str(), "struct"); + context->recover(); + } + $$.setBasic(EbtStruct, EvqTemporary, @1); + $$.userDef = structure; + context->exitStructDeclaration(); + } + | STRUCT LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { + TType* structure = new TType(new TStructure(NewPoolTString(""), $4)); + $$.setBasic(EbtStruct, EvqTemporary, @1); + $$.userDef = structure; + context->exitStructDeclaration(); + } + ; + +struct_declaration_list + : struct_declaration { + $$ = $1; + } + | struct_declaration_list struct_declaration { + $$ = $1; + for (size_t i = 0; i < $2->size(); ++i) { + TField* field = (*$2)[i]; + for (size_t j = 0; j < $$->size(); ++j) { + if ((*$$)[j]->name() == field->name()) { + context->error(@2, "duplicate field name in structure:", "struct", field->name().c_str()); + context->recover(); + } + } + $$->push_back(field); + } + } + ; + +struct_declaration + : type_specifier struct_declarator_list SEMICOLON { + $$ = $2; + + if (context->voidErrorCheck(@1, (*$2)[0]->name(), $1)) { + context->recover(); + } + for (unsigned int i = 0; i < $$->size(); ++i) { + // + // Careful not to replace already known aspects of type, like array-ness + // + TType* type = (*$$)[i]->type(); + type->setBasicType($1.type); + type->setNominalSize($1.size); + type->setMatrix($1.matrix); + type->setPrecision($1.precision); + + // don't allow arrays of arrays + if (type->isArray()) { + if (context->arrayTypeErrorCheck(@1, $1)) + context->recover(); + } + if ($1.array) + type->setArraySize($1.arraySize); + if ($1.userDef) + type->setStruct($1.userDef->getStruct()); + + if (context->structNestingErrorCheck(@1, *(*$$)[i])) + context->recover(); + } + } + ; + +struct_declarator_list + : struct_declarator { + $$ = NewPoolTFieldList(); + $$->push_back($1); + } + | struct_declarator_list COMMA struct_declarator { + $$->push_back($3); + } + ; + +struct_declarator + : identifier { + if (context->reservedErrorCheck(@1, *$1.string)) + context->recover(); + + TType* type = new TType(EbtVoid, EbpUndefined); + $$ = new TField(type, $1.string); + } + | identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { + if (context->reservedErrorCheck(@1, *$1.string)) + context->recover(); + + TType* type = new TType(EbtVoid, EbpUndefined); + int size = 0; + if (context->arraySizeErrorCheck(@3, $3, size)) + context->recover(); + type->setArraySize(size); + + $$ = new TField(type, $1.string); + } + ; + +initializer + : assignment_expression { $$ = $1; } + ; + +declaration_statement + : declaration { $$ = $1; } + ; + +statement + : compound_statement { $$ = $1; } + | simple_statement { $$ = $1; } + ; + +// Grammar Note: No labeled statements; 'goto' is not supported. + +simple_statement + : declaration_statement { $$ = $1; } + | expression_statement { $$ = $1; } + | selection_statement { $$ = $1; } + | iteration_statement { $$ = $1; } + | jump_statement { $$ = $1; } + ; + +compound_statement + : LEFT_BRACE RIGHT_BRACE { $$ = 0; } + | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE { + if ($3 != 0) { + $3->setOp(EOpSequence); + $3->setLine(@$); + } + $$ = $3; + } + ; + +statement_no_new_scope + : compound_statement_no_new_scope { $$ = $1; } + | simple_statement { $$ = $1; } + ; + +statement_with_scope + : { context->symbolTable.push(); } compound_statement_no_new_scope { context->symbolTable.pop(); $$ = $2; } + | { context->symbolTable.push(); } simple_statement { context->symbolTable.pop(); $$ = $2; } + ; + +compound_statement_no_new_scope + // Statement that doesn't create a new scope, for selection_statement, iteration_statement + : LEFT_BRACE RIGHT_BRACE { + $$ = 0; + } + | LEFT_BRACE statement_list RIGHT_BRACE { + if ($2) { + $2->setOp(EOpSequence); + $2->setLine(@$); + } + $$ = $2; + } + ; + +statement_list + : statement { + $$ = context->intermediate.makeAggregate($1, @$); + } + | statement_list statement { + $$ = context->intermediate.growAggregate($1, $2, @$); + } + ; + +expression_statement + : SEMICOLON { $$ = 0; } + | expression SEMICOLON { $$ = static_cast($1); } + ; + +selection_statement + : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement { + if (context->boolErrorCheck(@1, $3)) + context->recover(); + $$ = context->intermediate.addSelection($3, $5, @1); + } + ; + +selection_rest_statement + : statement_with_scope ELSE statement_with_scope { + $$.node1 = $1; + $$.node2 = $3; + } + | statement_with_scope { + $$.node1 = $1; + $$.node2 = 0; + } + ; + +// Grammar Note: No 'switch'. Switch statements not supported. + +condition + // In 1996 c++ draft, conditions can include single declarations + : expression { + $$ = $1; + if (context->boolErrorCheck($1->getLine(), $1)) + context->recover(); + } + | fully_specified_type identifier EQUAL initializer { + TIntermNode* intermNode; + if (context->structQualifierErrorCheck(@2, $1)) + context->recover(); + if (context->boolErrorCheck(@2, $1)) + context->recover(); + + if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode)) + $$ = $4; + else { + context->recover(); + $$ = 0; + } + } + ; + +iteration_statement + : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope { + context->symbolTable.pop(); + $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, @1); + --context->loopNestingLevel; + } + | DO { ++context->loopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { + if (context->boolErrorCheck(@8, $6)) + context->recover(); + + $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4); + --context->loopNestingLevel; + } + | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { + context->symbolTable.pop(); + $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast($5.node1), reinterpret_cast($5.node2), $7, @1); + --context->loopNestingLevel; + } + ; + +for_init_statement + : expression_statement { + $$ = $1; + } + | declaration_statement { + $$ = $1; + } + ; + +conditionopt + : condition { + $$ = $1; + } + | /* May be null */ { + $$ = 0; + } + ; + +for_rest_statement + : conditionopt SEMICOLON { + $$.node1 = $1; + $$.node2 = 0; + } + | conditionopt SEMICOLON expression { + $$.node1 = $1; + $$.node2 = $3; + } + ; + +jump_statement + : CONTINUE SEMICOLON { + if (context->loopNestingLevel <= 0) { + context->error(@1, "continue statement only allowed in loops", ""); + context->recover(); + } + $$ = context->intermediate.addBranch(EOpContinue, @1); + } + | BREAK SEMICOLON { + if (context->loopNestingLevel <= 0) { + context->error(@1, "break statement only allowed in loops", ""); + context->recover(); + } + $$ = context->intermediate.addBranch(EOpBreak, @1); + } + | RETURN SEMICOLON { + $$ = context->intermediate.addBranch(EOpReturn, @1); + if (context->currentFunctionType->getBasicType() != EbtVoid) { + context->error(@1, "non-void function must return a value", "return"); + context->recover(); + } + } + | RETURN expression SEMICOLON { + $$ = context->intermediate.addBranch(EOpReturn, $2, @1); + context->functionReturnsValue = true; + if (context->currentFunctionType->getBasicType() == EbtVoid) { + context->error(@1, "void function cannot return a value", "return"); + context->recover(); + } else if (*(context->currentFunctionType) != $2->getType()) { + context->error(@1, "function return is not matching type:", "return"); + context->recover(); + } + } + | DISCARD SEMICOLON { + FRAG_ONLY("discard", @1); + $$ = context->intermediate.addBranch(EOpKill, @1); + } + ; + +// Grammar Note: No 'goto'. Gotos are not supported. + +translation_unit + : external_declaration { + $$ = $1; + context->treeRoot = $$; + } + | translation_unit external_declaration { + $$ = context->intermediate.growAggregate($1, $2, @$); + context->treeRoot = $$; + } + ; + +external_declaration + : function_definition { + $$ = $1; + } + | declaration { + $$ = $1; + } + ; + +function_definition + : function_prototype { + TFunction* function = $1.function; + + const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName()); + + if (builtIn) + { + context->error(@1, "built-in functions cannot be redefined", function->getName().c_str()); + context->recover(); + } + + 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(@1, "function already has a body", function->getName().c_str()); + context->recover(); + } + prevDec->setDefined(); + + // + // Raise error message if main function takes any parameters or return anything other than void + // + if (function->getName() == "main") { + if (function->getParamCount() > 0) { + context->error(@1, "function cannot take any parameter(s)", function->getName().c_str()); + context->recover(); + } + if (function->getReturnType().getBasicType() != EbtVoid) { + context->error(@1, "", function->getReturnType().getBasicString(), "main function cannot return a value"); + context->recover(); + } + } + + // + // Remember the return type for later checking for RETURN statements. + // + context->currentFunctionType = &(prevDec->getReturnType()); + context->functionReturnsValue = false; + + // + // Insert parameters into the symbol table. + // If the parameter has no name, it's not an error, just don't insert it + // (could be used for unused args). + // + // Also, accumulate the list of parameters into the HIL, so lower level code + // knows where to find parameters. + // + TIntermAggregate* paramNodes = new TIntermAggregate; + for (size_t i = 0; i < function->getParamCount(); i++) { + const TParameter& param = function->getParam(i); + if (param.name != 0) { + TVariable *variable = new TVariable(param.name, *param.type); + // + // Insert the parameters with name in the symbol table. + // + if (! context->symbolTable.insert(*variable)) { + context->error(@1, "redefinition", variable->getName().c_str()); + context->recover(); + delete variable; + } + + // + // Add the parameter to the HIL + // + paramNodes = context->intermediate.growAggregate( + paramNodes, + context->intermediate.addSymbol(variable->getUniqueId(), + variable->getName(), + variable->getType(), + @1), + @1); + } else { + paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, @1), @1); + } + } + context->intermediate.setAggregateOperator(paramNodes, EOpParameters, @1); + $1.intermAggregate = paramNodes; + context->loopNestingLevel = 0; + } + compound_statement_no_new_scope { + //?? Check that all paths return a value if return type != void ? + // May be best done as post process phase on intermediate code + if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) { + context->error(@1, "function does not return a value:", "", $1.function->getName().c_str()); + context->recover(); + } + + $$ = context->intermediate.growAggregate($1.intermAggregate, $3, @$); + context->intermediate.setAggregateOperator($$, EOpFunction, @1); + $$->getAsAggregate()->setName($1.function->getMangledName().c_str()); + $$->getAsAggregate()->setType($1.function->getReturnType()); + + // store the pragma information for debug and optimize and other vendor specific + // information. This information can be queried from the parse tree + $$->getAsAggregate()->setOptimize(context->pragma().optimize); + $$->getAsAggregate()->setDebug(context->pragma().debug); + + context->symbolTable.pop(); + } + ; + +%% + +int glslang_parse(TParseContext* context) { + return yyparse(context); +} diff --git a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp new file mode 100644 index 0000000000..f2f918d77a --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp @@ -0,0 +1,424 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/localintermediate.h" + +// +// Two purposes: +// 1. Show an example of how to iterate tree. Functions can +// also directly call Traverse() on children themselves to +// have finer grained control over the process than shown here. +// See the last function for how to get started. +// 2. Print out a text based description of the tree. +// + +// +// Use this class to carry along data from node to node in +// the traversal +// +class TOutputTraverser : public TIntermTraverser { +public: + TOutputTraverser(TInfoSinkBase& i) : sink(i) { } + TInfoSinkBase& sink; + +protected: + void visitSymbol(TIntermSymbol*); + void visitConstantUnion(TIntermConstantUnion*); + bool visitBinary(Visit visit, TIntermBinary*); + bool visitUnary(Visit visit, TIntermUnary*); + bool visitSelection(Visit visit, TIntermSelection*); + bool visitAggregate(Visit visit, TIntermAggregate*); + bool visitLoop(Visit visit, TIntermLoop*); + bool visitBranch(Visit visit, TIntermBranch*); +}; + +TString TType::getCompleteString() const +{ + TStringStream stream; + + if (qualifier != EvqTemporary && qualifier != EvqGlobal) + stream << getQualifierString() << " " << getPrecisionString() << " "; + if (array) + stream << "array[" << getArraySize() << "] of "; + if (matrix) + stream << static_cast(size) << "X" << static_cast(size) << " matrix of "; + else if (size > 1) + stream << static_cast(size) << "-component vector of "; + + stream << getBasicString(); + return stream.str(); +} + +// +// Helper functions for printing, not part of traversing. +// + +void OutputTreeText(TInfoSinkBase& sink, TIntermNode* node, const int depth) +{ + int i; + + sink.location(node->getLine()); + + for (i = 0; i < depth; ++i) + sink << " "; +} + +// +// The rest of the file are the traversal functions. The last one +// is the one that starts the traversal. +// +// Return true from interior nodes to have the external traversal +// continue on to children. If you process children yourself, +// return false. +// + +void TOutputTraverser::visitSymbol(TIntermSymbol* node) +{ + OutputTreeText(sink, node, depth); + + sink << "'" << node->getSymbol() << "' "; + sink << "(" << node->getCompleteString() << ")\n"; +} + +bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node) +{ + TInfoSinkBase& out = sink; + + OutputTreeText(out, node, depth); + + switch (node->getOp()) { + case EOpAssign: out << "move second child to first child"; break; + case EOpInitialize: out << "initialize first child with second child"; break; + case EOpAddAssign: out << "add second child into first child"; break; + case EOpSubAssign: out << "subtract second child into first child"; break; + case EOpMulAssign: out << "multiply second child into first child"; break; + case EOpVectorTimesMatrixAssign: out << "matrix mult second child into first child"; break; + case EOpVectorTimesScalarAssign: out << "vector scale second child into first child"; break; + case EOpMatrixTimesScalarAssign: out << "matrix scale second child into first child"; break; + case EOpMatrixTimesMatrixAssign: out << "matrix mult second child into first child"; break; + case EOpDivAssign: out << "divide second child into first child"; break; + case EOpIndexDirect: out << "direct index"; break; + case EOpIndexIndirect: out << "indirect index"; break; + case EOpIndexDirectStruct: out << "direct index for structure"; break; + case EOpVectorSwizzle: out << "vector swizzle"; break; + + case EOpAdd: out << "add"; break; + case EOpSub: out << "subtract"; break; + case EOpMul: out << "component-wise multiply"; break; + case EOpDiv: out << "divide"; break; + case EOpEqual: out << "Compare Equal"; break; + case EOpNotEqual: out << "Compare Not Equal"; break; + case EOpLessThan: out << "Compare Less Than"; break; + case EOpGreaterThan: out << "Compare Greater Than"; break; + case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; + case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; + + case EOpVectorTimesScalar: out << "vector-scale"; break; + case EOpVectorTimesMatrix: out << "vector-times-matrix"; break; + case EOpMatrixTimesVector: out << "matrix-times-vector"; break; + case EOpMatrixTimesScalar: out << "matrix-scale"; break; + case EOpMatrixTimesMatrix: out << "matrix-multiply"; break; + + case EOpLogicalOr: out << "logical-or"; break; + case EOpLogicalXor: out << "logical-xor"; break; + case EOpLogicalAnd: out << "logical-and"; break; + default: out << ""; + } + + out << " (" << node->getCompleteString() << ")"; + + out << "\n"; + + return true; +} + +bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node) +{ + TInfoSinkBase& out = sink; + + OutputTreeText(out, node, depth); + + switch (node->getOp()) { + case EOpNegative: out << "Negate value"; break; + case EOpVectorLogicalNot: + case EOpLogicalNot: out << "Negate conditional"; break; + + case EOpPostIncrement: out << "Post-Increment"; break; + case EOpPostDecrement: out << "Post-Decrement"; break; + case EOpPreIncrement: out << "Pre-Increment"; break; + case EOpPreDecrement: out << "Pre-Decrement"; break; + + case EOpConvIntToBool: out << "Convert int to bool"; break; + case EOpConvFloatToBool:out << "Convert float to bool";break; + case EOpConvBoolToFloat:out << "Convert bool to float";break; + case EOpConvIntToFloat: out << "Convert int to float"; break; + case EOpConvFloatToInt: out << "Convert float to int"; break; + case EOpConvBoolToInt: out << "Convert bool to int"; break; + + case EOpRadians: out << "radians"; break; + case EOpDegrees: out << "degrees"; break; + case EOpSin: out << "sine"; break; + case EOpCos: out << "cosine"; break; + case EOpTan: out << "tangent"; break; + case EOpAsin: out << "arc sine"; break; + case EOpAcos: out << "arc cosine"; break; + case EOpAtan: out << "arc tangent"; break; + + case EOpExp: out << "exp"; break; + case EOpLog: out << "log"; break; + case EOpExp2: out << "exp2"; break; + case EOpLog2: out << "log2"; break; + case EOpSqrt: out << "sqrt"; break; + case EOpInverseSqrt: out << "inverse sqrt"; break; + + case EOpAbs: out << "Absolute value"; break; + case EOpSign: out << "Sign"; break; + case EOpFloor: out << "Floor"; break; + case EOpCeil: out << "Ceiling"; break; + case EOpFract: out << "Fraction"; break; + + case EOpLength: out << "length"; break; + case EOpNormalize: out << "normalize"; break; + // case EOpDPdx: out << "dPdx"; break; + // case EOpDPdy: out << "dPdy"; break; + // case EOpFwidth: out << "fwidth"; break; + + case EOpAny: out << "any"; break; + case EOpAll: out << "all"; break; + + default: + out.prefix(EPrefixError); + out << "Bad unary op"; + } + + out << " (" << node->getCompleteString() << ")"; + + out << "\n"; + + return true; +} + +bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node) +{ + TInfoSinkBase& out = sink; + + if (node->getOp() == EOpNull) { + out.prefix(EPrefixError); + out << "node is still EOpNull!"; + return true; + } + + OutputTreeText(out, node, depth); + + switch (node->getOp()) { + case EOpSequence: out << "Sequence\n"; return true; + case EOpComma: out << "Comma\n"; return true; + case EOpFunction: out << "Function Definition: " << node->getName(); break; + case EOpFunctionCall: out << "Function Call: " << node->getName(); break; + case EOpParameters: out << "Function Parameters: "; break; + + case EOpConstructFloat: out << "Construct float"; break; + case EOpConstructVec2: out << "Construct vec2"; break; + case EOpConstructVec3: out << "Construct vec3"; break; + case EOpConstructVec4: out << "Construct vec4"; break; + case EOpConstructBool: out << "Construct bool"; break; + case EOpConstructBVec2: out << "Construct bvec2"; break; + case EOpConstructBVec3: out << "Construct bvec3"; break; + case EOpConstructBVec4: out << "Construct bvec4"; break; + case EOpConstructInt: out << "Construct int"; break; + case EOpConstructIVec2: out << "Construct ivec2"; break; + case EOpConstructIVec3: out << "Construct ivec3"; break; + case EOpConstructIVec4: out << "Construct ivec4"; break; + case EOpConstructMat2: out << "Construct mat2"; break; + case EOpConstructMat3: out << "Construct mat3"; break; + case EOpConstructMat4: out << "Construct mat4"; break; + case EOpConstructStruct: out << "Construct structure"; break; + + case EOpLessThan: out << "Compare Less Than"; break; + case EOpGreaterThan: out << "Compare Greater Than"; break; + case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; + case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; + case EOpVectorEqual: out << "Equal"; break; + case EOpVectorNotEqual: out << "NotEqual"; break; + + case EOpMod: out << "mod"; break; + case EOpPow: out << "pow"; break; + + case EOpAtan: out << "arc tangent"; break; + + case EOpMin: out << "min"; break; + case EOpMax: out << "max"; break; + case EOpClamp: out << "clamp"; break; + case EOpMix: out << "mix"; break; + case EOpStep: out << "step"; break; + case EOpSmoothStep: out << "smoothstep"; break; + + case EOpDistance: out << "distance"; break; + case EOpDot: out << "dot-product"; break; + case EOpCross: out << "cross-product"; break; + case EOpFaceForward: out << "face-forward"; break; + case EOpReflect: out << "reflect"; break; + case EOpRefract: out << "refract"; break; + case EOpMul: out << "component-wise multiply"; break; + + case EOpDeclaration: out << "Declaration: "; break; + + default: + out.prefix(EPrefixError); + out << "Bad aggregation op"; + } + + if (node->getOp() != EOpSequence && node->getOp() != EOpParameters) + out << " (" << node->getCompleteString() << ")"; + + out << "\n"; + + return true; +} + +bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node) +{ + TInfoSinkBase& out = sink; + + OutputTreeText(out, node, depth); + + out << "Test condition and select"; + out << " (" << node->getCompleteString() << ")\n"; + + ++depth; + + OutputTreeText(sink, node, depth); + out << "Condition\n"; + node->getCondition()->traverse(this); + + OutputTreeText(sink, node, depth); + if (node->getTrueBlock()) { + out << "true case\n"; + node->getTrueBlock()->traverse(this); + } else + out << "true case is null\n"; + + if (node->getFalseBlock()) { + OutputTreeText(sink, node, depth); + out << "false case\n"; + node->getFalseBlock()->traverse(this); + } + + --depth; + + return false; +} + +void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) +{ + TInfoSinkBase& out = sink; + + size_t size = node->getType().getObjectSize(); + + for (size_t i = 0; i < size; i++) { + OutputTreeText(out, node, depth); + switch (node->getUnionArrayPointer()[i].getType()) { + case EbtBool: + if (node->getUnionArrayPointer()[i].getBConst()) + out << "true"; + else + out << "false"; + + out << " (" << "const bool" << ")"; + out << "\n"; + break; + case EbtFloat: + out << node->getUnionArrayPointer()[i].getFConst(); + out << " (const float)\n"; + break; + case EbtInt: + out << node->getUnionArrayPointer()[i].getIConst(); + out << " (const int)\n"; + break; + default: + out.message(EPrefixInternalError, node->getLine(), "Unknown constant"); + break; + } + } +} + +bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node) +{ + TInfoSinkBase& out = sink; + + OutputTreeText(out, node, depth); + + out << "Loop with condition "; + if (node->getType() == ELoopDoWhile) + out << "not "; + out << "tested first\n"; + + ++depth; + + OutputTreeText(sink, node, depth); + if (node->getCondition()) { + out << "Loop Condition\n"; + node->getCondition()->traverse(this); + } else + out << "No loop condition\n"; + + OutputTreeText(sink, node, depth); + if (node->getBody()) { + out << "Loop Body\n"; + node->getBody()->traverse(this); + } else + out << "No loop body\n"; + + if (node->getExpression()) { + OutputTreeText(sink, node, depth); + out << "Loop Terminal Expression\n"; + node->getExpression()->traverse(this); + } + + --depth; + + return false; +} + +bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node) +{ + TInfoSinkBase& out = sink; + + OutputTreeText(out, node, depth); + + switch (node->getFlowOp()) { + case EOpKill: out << "Branch: Kill"; break; + case EOpBreak: out << "Branch: Break"; break; + case EOpContinue: out << "Branch: Continue"; break; + case EOpReturn: out << "Branch: Return"; break; + default: out << "Branch: Unknown Branch"; break; + } + + if (node->getExpression()) { + out << " with expression\n"; + ++depth; + node->getExpression()->traverse(this); + --depth; + } else + out << "\n"; + + return false; +} + +// +// This function is the one to call externally to start the traversal. +// Individual functions can be initialized to 0 to skip processing of that +// type of node. It's children will still be processed. +// +void TIntermediate::outputTree(TIntermNode* root) +{ + if (root == 0) + return; + + TOutputTraverser it(infoSink.info); + + root->traverse(&it); +} diff --git a/src/3rdparty/angle/src/compiler/translator/intermediate.h b/src/3rdparty/angle/src/compiler/translator/intermediate.h new file mode 100644 index 0000000000..8f9fe23d3b --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/intermediate.h @@ -0,0 +1,635 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// +// Definition of the in-memory high-level intermediate representation +// of shaders. This is a tree that parser creates. +// +// Nodes in the tree are defined as a hierarchy of classes derived from +// TIntermNode. Each is a node in a tree. There is no preset branching factor; +// each node can have it's own type of list of children. +// + +#ifndef __INTERMEDIATE_H +#define __INTERMEDIATE_H + +#include "GLSLANG/ShaderLang.h" + +#include +#include "compiler/translator/Common.h" +#include "compiler/translator/Types.h" +#include "compiler/translator/ConstantUnion.h" + +// +// Operators used by the high-level (parse tree) representation. +// +enum TOperator { + EOpNull, // if in a node, should only mean a node is still being built + EOpSequence, // denotes a list of statements, or parameters, etc. + EOpFunctionCall, + EOpFunction, // For function definition + EOpParameters, // an aggregate listing the parameters to a function + + EOpDeclaration, + EOpPrototype, + + // + // Unary operators + // + + EOpNegative, + EOpLogicalNot, + EOpVectorLogicalNot, + + EOpPostIncrement, + EOpPostDecrement, + EOpPreIncrement, + EOpPreDecrement, + + EOpConvIntToBool, + EOpConvFloatToBool, + EOpConvBoolToFloat, + EOpConvIntToFloat, + EOpConvFloatToInt, + EOpConvBoolToInt, + + // + // binary operations + // + + EOpAdd, + EOpSub, + EOpMul, + EOpDiv, + EOpEqual, + EOpNotEqual, + EOpVectorEqual, + EOpVectorNotEqual, + EOpLessThan, + EOpGreaterThan, + EOpLessThanEqual, + EOpGreaterThanEqual, + EOpComma, + + EOpVectorTimesScalar, + EOpVectorTimesMatrix, + EOpMatrixTimesVector, + EOpMatrixTimesScalar, + + EOpLogicalOr, + EOpLogicalXor, + EOpLogicalAnd, + + EOpIndexDirect, + EOpIndexIndirect, + EOpIndexDirectStruct, + + EOpVectorSwizzle, + + // + // Built-in functions potentially mapped to operators + // + + EOpRadians, + EOpDegrees, + EOpSin, + EOpCos, + EOpTan, + EOpAsin, + EOpAcos, + EOpAtan, + + EOpPow, + EOpExp, + EOpLog, + EOpExp2, + EOpLog2, + EOpSqrt, + EOpInverseSqrt, + + EOpAbs, + EOpSign, + EOpFloor, + EOpCeil, + EOpFract, + EOpMod, + EOpMin, + EOpMax, + EOpClamp, + EOpMix, + EOpStep, + EOpSmoothStep, + + EOpLength, + EOpDistance, + EOpDot, + EOpCross, + EOpNormalize, + EOpFaceForward, + EOpReflect, + EOpRefract, + + EOpDFdx, // Fragment only, OES_standard_derivatives extension + EOpDFdy, // Fragment only, OES_standard_derivatives extension + EOpFwidth, // Fragment only, OES_standard_derivatives extension + + EOpMatrixTimesMatrix, + + EOpAny, + EOpAll, + + // + // Branch + // + + EOpKill, // Fragment only + EOpReturn, + EOpBreak, + EOpContinue, + + // + // Constructors + // + + EOpConstructInt, + EOpConstructBool, + EOpConstructFloat, + EOpConstructVec2, + EOpConstructVec3, + EOpConstructVec4, + EOpConstructBVec2, + EOpConstructBVec3, + EOpConstructBVec4, + EOpConstructIVec2, + EOpConstructIVec3, + EOpConstructIVec4, + EOpConstructMat2, + EOpConstructMat3, + EOpConstructMat4, + EOpConstructStruct, + + // + // moves + // + + EOpAssign, + EOpInitialize, + EOpAddAssign, + EOpSubAssign, + EOpMulAssign, + EOpVectorTimesMatrixAssign, + EOpVectorTimesScalarAssign, + EOpMatrixTimesScalarAssign, + EOpMatrixTimesMatrixAssign, + EOpDivAssign +}; + +extern const char* getOperatorString(TOperator op); + +class TIntermTraverser; +class TIntermAggregate; +class TIntermBinary; +class TIntermUnary; +class TIntermConstantUnion; +class TIntermSelection; +class TIntermTyped; +class TIntermSymbol; +class TIntermLoop; +class TInfoSink; + +// +// Base class for the tree nodes +// +class TIntermNode { +public: + POOL_ALLOCATOR_NEW_DELETE(); + TIntermNode() { + // TODO: Move this to TSourceLoc constructor + // after getting rid of TPublicType. + line.first_file = line.last_file = 0; + line.first_line = line.last_line = 0; + } + virtual ~TIntermNode() { } + + const TSourceLoc& getLine() const { return line; } + void setLine(const TSourceLoc& l) { line = l; } + + virtual void traverse(TIntermTraverser*) = 0; + virtual TIntermTyped* getAsTyped() { return 0; } + virtual TIntermConstantUnion* getAsConstantUnion() { return 0; } + virtual TIntermAggregate* getAsAggregate() { return 0; } + virtual TIntermBinary* getAsBinaryNode() { return 0; } + virtual TIntermUnary* getAsUnaryNode() { return 0; } + virtual TIntermSelection* getAsSelectionNode() { return 0; } + virtual TIntermSymbol* getAsSymbolNode() { return 0; } + virtual TIntermLoop* getAsLoopNode() { return 0; } + + // Replace a child node. Return true if |original| is a child + // node and it is replaced; otherwise, return false. + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement) = 0; + +protected: + TSourceLoc line; +}; + +// +// This is just to help yacc. +// +struct TIntermNodePair { + TIntermNode* node1; + TIntermNode* node2; +}; + +// +// Intermediate class for nodes that have a type. +// +class TIntermTyped : public TIntermNode { +public: + TIntermTyped(const TType& t) : type(t) { } + virtual TIntermTyped* getAsTyped() { return this; } + + virtual bool hasSideEffects() const = 0; + + void setType(const TType& t) { type = t; } + const TType& getType() const { return type; } + TType* getTypePointer() { return &type; } + + TBasicType getBasicType() const { return type.getBasicType(); } + TQualifier getQualifier() const { return type.getQualifier(); } + TPrecision getPrecision() const { return type.getPrecision(); } + int getNominalSize() const { return type.getNominalSize(); } + + bool isMatrix() const { return type.isMatrix(); } + bool isArray() const { return type.isArray(); } + bool isVector() const { return type.isVector(); } + bool isScalar() const { return type.isScalar(); } + const char* getBasicString() const { return type.getBasicString(); } + const char* getQualifierString() const { return type.getQualifierString(); } + TString getCompleteString() const { return type.getCompleteString(); } + + int totalRegisterCount() const { return type.totalRegisterCount(); } + int elementRegisterCount() const { return type.elementRegisterCount(); } + int getArraySize() const { return type.getArraySize(); } + +protected: + TType type; +}; + +// +// Handle for, do-while, and while loops. +// +enum TLoopType { + ELoopFor, + ELoopWhile, + ELoopDoWhile +}; + +class TIntermLoop : public TIntermNode { +public: + TIntermLoop(TLoopType aType, + TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr, + TIntermNode* aBody) : + type(aType), + init(aInit), + cond(aCond), + expr(aExpr), + body(aBody), + unrollFlag(false) { } + + virtual TIntermLoop* getAsLoopNode() { return this; } + virtual void traverse(TIntermTraverser*); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + TLoopType getType() const { return type; } + TIntermNode* getInit() { return init; } + TIntermTyped* getCondition() { return cond; } + TIntermTyped* getExpression() { return expr; } + TIntermNode* getBody() { return body; } + + void setUnrollFlag(bool flag) { unrollFlag = flag; } + bool getUnrollFlag() { return unrollFlag; } + +protected: + TLoopType type; + TIntermNode* init; // for-loop initialization + TIntermTyped* cond; // loop exit condition + TIntermTyped* expr; // for-loop expression + TIntermNode* body; // loop body + + bool unrollFlag; // Whether the loop should be unrolled or not. +}; + +// +// Handle break, continue, return, and kill. +// +class TIntermBranch : public TIntermNode { +public: + TIntermBranch(TOperator op, TIntermTyped* e) : + flowOp(op), + expression(e) { } + + virtual void traverse(TIntermTraverser*); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + TOperator getFlowOp() { return flowOp; } + TIntermTyped* getExpression() { return expression; } + +protected: + TOperator flowOp; + TIntermTyped* expression; // non-zero except for "return exp;" statements +}; + +// +// Nodes that correspond to symbols or constants in the source code. +// +class TIntermSymbol : public TIntermTyped { +public: + // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from + // per process globalpoolallocator, then it causes increased memory usage per compile + // it is essential to use "symbol = sym" to assign to symbol + TIntermSymbol(int i, const TString& sym, const TType& t) : + TIntermTyped(t), id(i) { symbol = sym; originalSymbol = sym; } + + virtual bool hasSideEffects() const { return false; } + + int getId() const { return id; } + const TString& getSymbol() const { return symbol; } + + void setId(int newId) { id = newId; } + void setSymbol(const TString& sym) { symbol = sym; } + + const TString& getOriginalSymbol() const { return originalSymbol; } + + virtual void traverse(TIntermTraverser*); + virtual TIntermSymbol* getAsSymbolNode() { return this; } + virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } + +protected: + int id; + TString symbol; + TString originalSymbol; +}; + +class TIntermConstantUnion : public TIntermTyped { +public: + TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { } + + virtual bool hasSideEffects() const { return false; } + + ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; } + + int getIConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; } + float getFConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; } + bool getBConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; } + + virtual TIntermConstantUnion* getAsConstantUnion() { return this; } + virtual void traverse(TIntermTraverser*); + virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } + + TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&); + +protected: + ConstantUnion *unionArrayPointer; +}; + +// +// Intermediate class for node types that hold operators. +// +class TIntermOperator : public TIntermTyped { +public: + TOperator getOp() const { return op; } + void setOp(TOperator o) { op = o; } + + bool isAssignment() const; + bool isConstructor() const; + + virtual bool hasSideEffects() const { return isAssignment(); } + +protected: + TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {} + TIntermOperator(TOperator o, const TType& t) : TIntermTyped(t), op(o) {} + TOperator op; +}; + +// +// Nodes for all the basic binary math operators. +// +class TIntermBinary : public TIntermOperator { +public: + TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {} + + virtual TIntermBinary* getAsBinaryNode() { return this; } + virtual void traverse(TIntermTraverser*); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + virtual bool hasSideEffects() const { return (isAssignment() || left->hasSideEffects() || right->hasSideEffects()); } + + void setLeft(TIntermTyped* n) { left = n; } + void setRight(TIntermTyped* n) { right = n; } + TIntermTyped* getLeft() const { return left; } + TIntermTyped* getRight() const { return right; } + bool promote(TInfoSink&); + + void setAddIndexClamp() { addIndexClamp = true; } + bool getAddIndexClamp() { return addIndexClamp; } + +protected: + TIntermTyped* left; + TIntermTyped* right; + + // If set to true, wrap any EOpIndexIndirect with a clamp to bounds. + bool addIndexClamp; +}; + +// +// Nodes for unary math operators. +// +class TIntermUnary : public TIntermOperator { +public: + TIntermUnary(TOperator o, const TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {} + TIntermUnary(TOperator o) : TIntermOperator(o), operand(0), useEmulatedFunction(false) {} + + virtual void traverse(TIntermTraverser*); + virtual TIntermUnary* getAsUnaryNode() { return this; } + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + virtual bool hasSideEffects() const { return (isAssignment() || operand->hasSideEffects()); } + + void setOperand(TIntermTyped* o) { operand = o; } + TIntermTyped* getOperand() { return operand; } + bool promote(TInfoSink&); + + void setUseEmulatedFunction() { useEmulatedFunction = true; } + bool getUseEmulatedFunction() { return useEmulatedFunction; } + +protected: + TIntermTyped* operand; + + // If set to true, replace the built-in function call with an emulated one + // to work around driver bugs. + bool useEmulatedFunction; +}; + +typedef TVector TIntermSequence; +typedef TVector TQualifierList; + +// +// Nodes that operate on an arbitrary sized set of children. +// +class TIntermAggregate : public TIntermOperator { +public: + TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { } + TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { } + ~TIntermAggregate() { } + + virtual TIntermAggregate* getAsAggregate() { return this; } + virtual void traverse(TIntermTraverser*); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + // Conservatively assume function calls and other aggregate operators have side-effects + virtual bool hasSideEffects() const { return true; } + + TIntermSequence& getSequence() { return sequence; } + + void setName(const TString& n) { name = n; } + const TString& getName() const { return name; } + + void setUserDefined() { userDefined = true; } + bool isUserDefined() const { return userDefined; } + + void setOptimize(bool o) { optimize = o; } + bool getOptimize() { return optimize; } + void setDebug(bool d) { debug = d; } + bool getDebug() { return debug; } + + void setUseEmulatedFunction() { useEmulatedFunction = true; } + bool getUseEmulatedFunction() { return useEmulatedFunction; } + +protected: + TIntermAggregate(const TIntermAggregate&); // disallow copy constructor + TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator + TIntermSequence sequence; + TString name; + bool userDefined; // used for user defined function names + + bool optimize; + bool debug; + + // If set to true, replace the built-in function call with an emulated one + // to work around driver bugs. + bool useEmulatedFunction; +}; + +// +// For if tests. Simplified since there is no switch statement. +// +class TIntermSelection : public TIntermTyped { +public: + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : + TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {} + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : + TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {} + + virtual void traverse(TIntermTraverser*); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + // Conservatively assume selections have side-effects + virtual bool hasSideEffects() const { return true; } + + bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } + TIntermNode* getCondition() const { return condition; } + TIntermNode* getTrueBlock() const { return trueBlock; } + TIntermNode* getFalseBlock() const { return falseBlock; } + TIntermSelection* getAsSelectionNode() { return this; } + +protected: + TIntermTyped* condition; + TIntermNode* trueBlock; + TIntermNode* falseBlock; +}; + +enum Visit +{ + PreVisit, + InVisit, + PostVisit +}; + +// +// For traversing the tree. User should derive from this, +// put their traversal specific data in it, and then pass +// it to a Traverse method. +// +// When using this, just fill in the methods for nodes you want visited. +// Return false from a pre-visit to skip visiting that node's subtree. +// +class TIntermTraverser +{ +public: + POOL_ALLOCATOR_NEW_DELETE(); + TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : + preVisit(preVisit), + inVisit(inVisit), + postVisit(postVisit), + rightToLeft(rightToLeft), + depth(0), + maxDepth(0) {} + virtual ~TIntermTraverser() {} + + virtual void visitSymbol(TIntermSymbol*) {} + virtual void visitConstantUnion(TIntermConstantUnion*) {} + virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;} + virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;} + virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;} + virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;} + virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;} + virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;} + + int getMaxDepth() const {return maxDepth;} + + void incrementDepth(TIntermNode *current) + { + depth++; + maxDepth = std::max(maxDepth, depth); + path.push_back(current); + } + + void decrementDepth() + { + depth--; + path.pop_back(); + } + + TIntermNode *getParentNode() + { + return path.size() == 0 ? NULL : path.back(); + } + + // Return the original name if hash function pointer is NULL; + // otherwise return the hashed name. + static TString hash(const TString& name, ShHashFunction64 hashFunction); + + const bool preVisit; + const bool inVisit; + const bool postVisit; + const bool rightToLeft; + +protected: + int depth; + int maxDepth; + + // All the nodes from root to the current node's parent during traversing. + TVector path; +}; + +#endif // __INTERMEDIATE_H diff --git a/src/3rdparty/angle/src/compiler/translator/localintermediate.h b/src/3rdparty/angle/src/compiler/translator/localintermediate.h new file mode 100644 index 0000000000..b582e02f5d --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/localintermediate.h @@ -0,0 +1,57 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _LOCAL_INTERMEDIATE_INCLUDED_ +#define _LOCAL_INTERMEDIATE_INCLUDED_ + +#include "GLSLANG/ShaderLang.h" +#include "compiler/translator/intermediate.h" +#include "compiler/translator/SymbolTable.h" + +struct TVectorFields { + int offsets[4]; + int num; +}; + +// +// Set of helper functions to help parse and build the tree. +// +class TInfoSink; +class TIntermediate { +public: + POOL_ALLOCATOR_NEW_DELETE(); + TIntermediate(TInfoSink& i) : infoSink(i) { } + + TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TSourceLoc&); + TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); + TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&, TSymbolTable&); + TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); + TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&); + TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, const TSourceLoc&, TSymbolTable&); + TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&); + TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&); + TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, const TSourceLoc&); + TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&); + TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&); + TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); + TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, const TSourceLoc&); + TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ; + bool parseConstTree(const TSourceLoc&, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false); + TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, const TSourceLoc&); + TIntermBranch* addBranch(TOperator, const TSourceLoc&); + TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&); + TIntermTyped* addSwizzle(TVectorFields&, const TSourceLoc&); + bool postProcess(TIntermNode*); + void remove(TIntermNode*); + void outputTree(TIntermNode*); + +private: + void operator=(TIntermediate&); // prevent assignments + + TInfoSink& infoSink; +}; + +#endif // _LOCAL_INTERMEDIATE_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/osinclude.h b/src/3rdparty/angle/src/compiler/translator/osinclude.h new file mode 100644 index 0000000000..cccfa6355c --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/osinclude.h @@ -0,0 +1,64 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef __OSINCLUDE_H +#define __OSINCLUDE_H + +// +// This file contains contains os-specific datatypes and +// declares any os-specific functions. +// + +#if defined(_WIN32) || defined(_WIN64) +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) +#define ANGLE_OS_WINRT +#else +#define ANGLE_OS_WIN +#endif +#elif defined(__APPLE__) || defined(__linux__) || \ + defined(__FreeBSD__) || defined(__OpenBSD__) || \ + defined(__NetBSD__) || defined(__DragonFly__) || \ + defined(__sun) || defined(ANDROID) || \ + defined(__GLIBC__) || defined(__GNU__) || \ + defined(__QNX__) +#define ANGLE_OS_POSIX +#else +#error Unsupported platform. +#endif + +#if defined(ANGLE_OS_WIN) || defined(ANGLE_OS_WINRT) +#define STRICT +#define VC_EXTRALEAN 1 +#include +#elif defined(ANGLE_OS_POSIX) +#include +#include +#include +#endif // ANGLE_OS_WIN + + +#include "compiler/translator/compilerdebug.h" + +// +// Thread Local Storage Operations +// +#if defined(ANGLE_OS_WIN) +typedef DWORD OS_TLSIndex; +#define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES) +#elif defined(ANGLE_OS_WINRT) +typedef size_t OS_TLSIndex; +#define OS_INVALID_TLS_INDEX ((DWORD)0xFFFFFF) +#elif defined(ANGLE_OS_POSIX) +typedef pthread_key_t OS_TLSIndex; +#define OS_INVALID_TLS_INDEX (static_cast(-1)) +#endif // ANGLE_OS_WIN + +OS_TLSIndex OS_AllocTLSIndex(); +void *OS_GetTLSValue(OS_TLSIndex nIndex); +bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue); +bool OS_FreeTLSIndex(OS_TLSIndex nIndex); + +#endif // __OSINCLUDE_H diff --git a/src/3rdparty/angle/src/compiler/translator/ossource_posix.cpp b/src/3rdparty/angle/src/compiler/translator/ossource_posix.cpp new file mode 100644 index 0000000000..d4bba4c70e --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ossource_posix.cpp @@ -0,0 +1,72 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// +// This file contains the posix specific functions +// +#include "compiler/translator/osinclude.h" + +#if !defined(ANGLE_OS_POSIX) +#error Trying to build a posix specific file in a non-posix build. +#endif + +// +// Thread Local Storage Operations +// +OS_TLSIndex OS_AllocTLSIndex() +{ + pthread_key_t pPoolIndex; + + // + // Create global pool key. + // + if ((pthread_key_create(&pPoolIndex, NULL)) != 0) { + assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage"); + return false; + } + else { + return pPoolIndex; + } +} + + +void *OS_GetTLSValue(OS_TLSIndex nIndex) +{ + ASSERT(nIndex != OS_INVALID_TLS_INDEX); + + return pthread_getspecific(nIndex); +} + + +bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) +{ + if (nIndex == OS_INVALID_TLS_INDEX) { + assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); + return false; + } + + if (pthread_setspecific(nIndex, lpvValue) == 0) + return true; + else + return false; +} + + +bool OS_FreeTLSIndex(OS_TLSIndex nIndex) +{ + if (nIndex == OS_INVALID_TLS_INDEX) { + assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); + return false; + } + + // + // Delete the global pool key. + // + if (pthread_key_delete(nIndex) == 0) + return true; + else + return false; +} diff --git a/src/3rdparty/angle/src/compiler/translator/ossource_win.cpp b/src/3rdparty/angle/src/compiler/translator/ossource_win.cpp new file mode 100644 index 0000000000..abd8bc7833 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ossource_win.cpp @@ -0,0 +1,65 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/osinclude.h" +// +// This file contains contains the window's specific functions +// + +#if !defined(ANGLE_OS_WIN) +#error Trying to build a windows specific file in a non windows build. +#endif + + +// +// Thread Local Storage Operations +// +OS_TLSIndex OS_AllocTLSIndex() +{ + DWORD dwIndex = TlsAlloc(); + if (dwIndex == TLS_OUT_OF_INDEXES) { + assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage"); + return OS_INVALID_TLS_INDEX; + } + + return dwIndex; +} + + +void *OS_GetTLSValue(OS_TLSIndex nIndex) +{ + ASSERT(nIndex != OS_INVALID_TLS_INDEX); + + return TlsGetValue(nIndex); +} + + +bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) +{ + if (nIndex == OS_INVALID_TLS_INDEX) { + assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); + return false; + } + + if (TlsSetValue(nIndex, lpvValue)) + return true; + else + return false; +} + + +bool OS_FreeTLSIndex(OS_TLSIndex nIndex) +{ + if (nIndex == OS_INVALID_TLS_INDEX) { + assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); + return false; + } + + if (TlsFree(nIndex)) + return true; + else + return false; +} diff --git a/src/3rdparty/angle/src/compiler/translator/ossource_winrt.cpp b/src/3rdparty/angle/src/compiler/translator/ossource_winrt.cpp new file mode 100644 index 0000000000..bb061ca85d --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ossource_winrt.cpp @@ -0,0 +1,75 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/osinclude.h" +// +// This file contains contains Windows Runtime specific functions +// + +#if !defined(ANGLE_OS_WINRT) +#error Trying to build a WinRT specific file in a non-WinRT build. +#endif + +#include + + +// +// Thread Local Storage Operations +// +__declspec(thread) std::vector *tls = nullptr; +__declspec(thread) std::vector *freeIndices = nullptr; + +OS_TLSIndex OS_AllocTLSIndex() +{ + if (!tls) + tls = new std::vector; + + if (freeIndices && !freeIndices->empty()) { + OS_TLSIndex index = freeIndices->back(); + freeIndices->pop_back(); + return index; + } else { + tls->push_back(nullptr); + return tls->size() - 1; + } +} + + +void *OS_GetTLSValue(OS_TLSIndex nIndex) +{ + ASSERT(nIndex != OS_INVALID_TLS_INDEX); + ASSERT(tls); + + return tls->at(nIndex); +} + + +bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) +{ + if (!tls || nIndex >= tls->size() || nIndex == OS_INVALID_TLS_INDEX) { + ASSERT(0 && "OS_SetTLSValue(): Invalid TLS Index"); + return false; + } + + tls->at(nIndex) = lpvValue; + return true; +} + + +bool OS_FreeTLSIndex(OS_TLSIndex nIndex) +{ + if (!tls || nIndex >= tls->size() || nIndex == OS_INVALID_TLS_INDEX) { + ASSERT(0 && "OS_SetTLSValue(): Invalid TLS Index"); + return false; + } + + if (!freeIndices) + freeIndices = new std::vector; + + freeIndices->push_back(nIndex); + + return true; +} diff --git a/src/3rdparty/angle/src/compiler/translator/parseConst.cpp b/src/3rdparty/angle/src/compiler/translator/parseConst.cpp new file mode 100644 index 0000000000..a59f0be9d8 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/parseConst.cpp @@ -0,0 +1,245 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/ParseContext.h" + +// +// Use this class to carry along data from node to node in +// the traversal +// +class TConstTraverser : public TIntermTraverser { +public: + TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t) + : error(false), + index(0), + unionArray(cUnion), + type(t), + constructorType(constructType), + singleConstantParam(singleConstParam), + infoSink(sink), + symbolTable(symTable), + size(0), + isMatrix(false), + matrixSize(0) { + } + + bool error; + +protected: + void visitSymbol(TIntermSymbol*); + void visitConstantUnion(TIntermConstantUnion*); + bool visitBinary(Visit visit, TIntermBinary*); + bool visitUnary(Visit visit, TIntermUnary*); + bool visitSelection(Visit visit, TIntermSelection*); + bool visitAggregate(Visit visit, TIntermAggregate*); + bool visitLoop(Visit visit, TIntermLoop*); + bool visitBranch(Visit visit, TIntermBranch*); + + size_t index; + ConstantUnion *unionArray; + TType type; + TOperator constructorType; + bool singleConstantParam; + TInfoSink& infoSink; + TSymbolTable& symbolTable; + size_t size; // size of the constructor ( 4 for vec4) + bool isMatrix; + size_t matrixSize; // dimension of the matrix (nominal size and not the instance size) +}; + +// +// The rest of the file are the traversal functions. The last one +// is the one that starts the traversal. +// +// Return true from interior nodes to have the external traversal +// continue on to children. If you process children yourself, +// return false. +// + +void TConstTraverser::visitSymbol(TIntermSymbol* node) +{ + infoSink.info.message(EPrefixInternalError, node->getLine(), "Symbol Node found in constant constructor"); + return; + +} + +bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node) +{ + TQualifier qualifier = node->getType().getQualifier(); + + if (qualifier != EvqConst) { + TString buf; + buf.append("'constructor' : assigning non-constant to "); + buf.append(type.getCompleteString()); + infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); + error = true; + return false; + } + + infoSink.info.message(EPrefixInternalError, node->getLine(), "Binary Node found in constant constructor"); + + return false; +} + +bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node) +{ + TString buf; + buf.append("'constructor' : assigning non-constant to "); + buf.append(type.getCompleteString()); + infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); + error = true; + return false; +} + +bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node) +{ + if (!node->isConstructor() && node->getOp() != EOpComma) { + TString buf; + buf.append("'constructor' : assigning non-constant to "); + buf.append(type.getCompleteString()); + infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); + error = true; + return false; + } + + if (node->getSequence().size() == 0) { + error = true; + return false; + } + + bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion(); + if (flag) + { + singleConstantParam = true; + constructorType = node->getOp(); + size = node->getType().getObjectSize(); + + if (node->getType().isMatrix()) { + isMatrix = true; + matrixSize = node->getType().getNominalSize(); + } + } + + for (TIntermSequence::iterator p = node->getSequence().begin(); + p != node->getSequence().end(); p++) { + + if (node->getOp() == EOpComma) + index = 0; + + (*p)->traverse(this); + } + if (flag) + { + singleConstantParam = false; + constructorType = EOpNull; + size = 0; + isMatrix = false; + matrixSize = 0; + } + return false; +} + +bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node) +{ + infoSink.info.message(EPrefixInternalError, node->getLine(), "Selection Node found in constant constructor"); + error = true; + return false; +} + +void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) +{ + if (!node->getUnionArrayPointer()) + { + // The constant was not initialized, this should already have been logged + assert(infoSink.info.size() != 0); + return; + } + + ConstantUnion* leftUnionArray = unionArray; + size_t instanceSize = type.getObjectSize(); + + if (index >= instanceSize) + return; + + if (!singleConstantParam) { + size_t size = node->getType().getObjectSize(); + + ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); + for (size_t i = 0; i < size; i++) { + if (index >= instanceSize) + return; + leftUnionArray[index] = rightUnionArray[i]; + + (index)++; + } + } else { + size_t totalSize = index + size; + ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); + if (!isMatrix) { + size_t count = 0; + for (size_t i = index; i < totalSize; i++) { + if (i >= instanceSize) + return; + + leftUnionArray[i] = rightUnionArray[count]; + + (index)++; + + if (node->getType().getObjectSize() > 1) + count++; + } + } else { // for matrix constructors + size_t count = 0; + size_t element = index; + for (size_t i = index; i < totalSize; i++) { + if (i >= instanceSize) + return; + if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 ) + leftUnionArray[i] = rightUnionArray[count]; + else + leftUnionArray[i].setFConst(0.0f); + + (index)++; + + if (node->getType().getObjectSize() > 1) + count++; + } + } + } +} + +bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node) +{ + infoSink.info.message(EPrefixInternalError, node->getLine(), "Loop Node found in constant constructor"); + error = true; + return false; +} + +bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node) +{ + infoSink.info.message(EPrefixInternalError, node->getLine(), "Branch Node found in constant constructor"); + error = true; + return false; +} + +// +// This function is the one to call externally to start the traversal. +// Individual functions can be initialized to 0 to skip processing of that +// type of node. It's children will still be processed. +// +bool TIntermediate::parseConstTree(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam) +{ + if (root == 0) + return false; + + TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t); + + root->traverse(&it); + if (it.error) + return true; + else + return false; +} diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp new file mode 100644 index 0000000000..a9f3f49ef3 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp @@ -0,0 +1,127 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/ParseContext.h" +#include "compiler/translator/depgraph/DependencyGraphOutput.h" +#include "compiler/translator/timing/RestrictFragmentShaderTiming.h" + +RestrictFragmentShaderTiming::RestrictFragmentShaderTiming(TInfoSinkBase& sink) + : mSink(sink) + , mNumErrors(0) +{ + // Sampling ops found only in fragment shaders. + mSamplingOps.insert("texture2D(s21;vf2;f1;"); + mSamplingOps.insert("texture2DProj(s21;vf3;f1;"); + mSamplingOps.insert("texture2DProj(s21;vf4;f1;"); + mSamplingOps.insert("textureCube(sC1;vf3;f1;"); + // Sampling ops found in both vertex and fragment shaders. + mSamplingOps.insert("texture2D(s21;vf2;"); + mSamplingOps.insert("texture2DProj(s21;vf3;"); + mSamplingOps.insert("texture2DProj(s21;vf4;"); + mSamplingOps.insert("textureCube(sC1;vf3;"); + // Sampling ops provided by OES_EGL_image_external. + mSamplingOps.insert("texture2D(1;vf2;"); + mSamplingOps.insert("texture2DProj(1;vf3;"); + mSamplingOps.insert("texture2DProj(1;vf4;"); + // Sampling ops provided by ARB_texture_rectangle. + mSamplingOps.insert("texture2DRect(1;vf2;"); + mSamplingOps.insert("texture2DRectProj(1;vf3;"); + mSamplingOps.insert("texture2DRectProj(1;vf4;"); +} + +// FIXME(mvujovic): We do not know if the execution time of built-in operations like sin, pow, etc. +// can vary based on the value of the input arguments. If so, we should restrict those as well. +void RestrictFragmentShaderTiming::enforceRestrictions(const TDependencyGraph& graph) +{ + mNumErrors = 0; + + // FIXME(mvujovic): The dependency graph does not support user defined function calls right now, + // so we generate errors for them. + validateUserDefinedFunctionCallUsage(graph); + + // Starting from each sampler, traverse the dependency graph and generate an error each time we + // hit a node where sampler dependent values are not allowed. + for (TGraphSymbolVector::const_iterator iter = graph.beginSamplerSymbols(); + iter != graph.endSamplerSymbols(); + ++iter) + { + TGraphSymbol* samplerSymbol = *iter; + clearVisited(); + samplerSymbol->traverse(this); + } +} + +void RestrictFragmentShaderTiming::validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph) +{ + for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls(); + iter != graph.endUserDefinedFunctionCalls(); + ++iter) + { + TGraphFunctionCall* functionCall = *iter; + beginError(functionCall->getIntermFunctionCall()); + mSink << "A call to a user defined function is not permitted.\n"; + } +} + +void RestrictFragmentShaderTiming::beginError(const TIntermNode* node) +{ + ++mNumErrors; + mSink.prefix(EPrefixError); + mSink.location(node->getLine()); +} + +bool RestrictFragmentShaderTiming::isSamplingOp(const TIntermAggregate* intermFunctionCall) const +{ + return !intermFunctionCall->isUserDefined() && + mSamplingOps.find(intermFunctionCall->getName()) != mSamplingOps.end(); +} + +void RestrictFragmentShaderTiming::visitArgument(TGraphArgument* parameter) +{ + // Texture cache access time might leak sensitive information. + // Thus, we restrict sampler dependent values from affecting the coordinate or LOD bias of a + // sampling operation. + if (isSamplingOp(parameter->getIntermFunctionCall())) { + switch (parameter->getArgumentNumber()) { + case 1: + // Second argument (coord) + beginError(parameter->getIntermFunctionCall()); + mSink << "An expression dependent on a sampler is not permitted to be the" + << " coordinate argument of a sampling operation.\n"; + break; + case 2: + // Third argument (bias) + beginError(parameter->getIntermFunctionCall()); + mSink << "An expression dependent on a sampler is not permitted to be the" + << " bias argument of a sampling operation.\n"; + break; + default: + // First argument (sampler) + break; + } + } +} + +void RestrictFragmentShaderTiming::visitSelection(TGraphSelection* selection) +{ + beginError(selection->getIntermSelection()); + mSink << "An expression dependent on a sampler is not permitted in a conditional statement.\n"; +} + +void RestrictFragmentShaderTiming::visitLoop(TGraphLoop* loop) +{ + beginError(loop->getIntermLoop()); + mSink << "An expression dependent on a sampler is not permitted in a loop condition.\n"; +} + +void RestrictFragmentShaderTiming::visitLogicalOp(TGraphLogicalOp* logicalOp) +{ + beginError(logicalOp->getIntermLogicalOp()); + mSink << "An expression dependent on a sampler is not permitted on the left hand side of a logical " + << logicalOp->getOpString() + << " operator.\n"; +} diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h new file mode 100644 index 0000000000..323cb62d8a --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ +#define COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ + +#include "GLSLANG/ShaderLang.h" + +#include "compiler/translator/intermediate.h" +#include "compiler/translator/depgraph/DependencyGraph.h" + +class TInfoSinkBase; + +class RestrictFragmentShaderTiming : TDependencyGraphTraverser { +public: + RestrictFragmentShaderTiming(TInfoSinkBase& sink); + void enforceRestrictions(const TDependencyGraph& graph); + int numErrors() const { return mNumErrors; } + + virtual void visitArgument(TGraphArgument* parameter); + virtual void visitSelection(TGraphSelection* selection); + virtual void visitLoop(TGraphLoop* loop); + virtual void visitLogicalOp(TGraphLogicalOp* logicalOp); + +private: + void beginError(const TIntermNode* node); + void validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph); + bool isSamplingOp(const TIntermAggregate* intermFunctionCall) const; + + TInfoSinkBase& mSink; + int mNumErrors; + + typedef std::set StringSet; + StringSet mSamplingOps; +}; + +#endif // COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp new file mode 100644 index 0000000000..ee78c35450 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp @@ -0,0 +1,17 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/timing/RestrictVertexShaderTiming.h" + +void RestrictVertexShaderTiming::visitSymbol(TIntermSymbol* node) +{ + if (IsSampler(node->getBasicType())) { + ++mNumErrors; + mSink.message(EPrefixError, + node->getLine(), + "Samplers are not permitted in vertex shaders"); + } +} diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h new file mode 100644 index 0000000000..5f0dd3197a --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h @@ -0,0 +1,33 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ +#define COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ + +#include "GLSLANG/ShaderLang.h" + +#include "compiler/translator/intermediate.h" +#include "compiler/translator/InfoSink.h" + +class TInfoSinkBase; + +class RestrictVertexShaderTiming : public TIntermTraverser { +public: + RestrictVertexShaderTiming(TInfoSinkBase& sink) + : TIntermTraverser(true, false, false) + , mSink(sink) + , mNumErrors(0) {} + + void enforceRestrictions(TIntermNode* root) { root->traverse(this); } + int numErrors() { return mNumErrors; } + + virtual void visitSymbol(TIntermSymbol*); +private: + TInfoSinkBase& mSink; + int mNumErrors; +}; + +#endif // COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/util.cpp b/src/3rdparty/angle/src/compiler/translator/util.cpp new file mode 100644 index 0000000000..077bdcc48b --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/util.cpp @@ -0,0 +1,28 @@ +// +// 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 "compiler/translator/util.h" + +#include + +#include "compiler/preprocessor/numeric_lex.h" + +bool atof_clamp(const char *str, float *value) +{ + bool success = pp::numeric_lex_float(str, value); + if (!success) + *value = std::numeric_limits::max(); + return success; +} + +bool atoi_clamp(const char *str, int *value) +{ + bool success = pp::numeric_lex_int(str, value); + if (!success) + *value = std::numeric_limits::max(); + return success; +} + diff --git a/src/3rdparty/angle/src/compiler/translator/util.h b/src/3rdparty/angle/src/compiler/translator/util.h new file mode 100644 index 0000000000..dc69f39060 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/util.h @@ -0,0 +1,20 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_UTIL_H +#define COMPILER_UTIL_H + +// atof_clamp is like atof but +// 1. it forces C locale, i.e. forcing '.' as decimal point. +// 2. it clamps the value to -FLT_MAX or FLT_MAX if overflow happens. +// Return false if overflow happens. +extern bool atof_clamp(const char *str, float *value); + +// If overflow happens, clamp the value to INT_MIN or INT_MAX. +// Return false if overflow happens. +extern bool atoi_clamp(const char *str, int *value); + +#endif // COMPILER_UTIL_H diff --git a/src/3rdparty/angle/src/compiler/util.cpp b/src/3rdparty/angle/src/compiler/util.cpp deleted file mode 100644 index d6e5eeed91..0000000000 --- a/src/3rdparty/angle/src/compiler/util.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// 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 "compiler/util.h" - -#include - -#include "compiler/preprocessor/numeric_lex.h" - -bool atof_clamp(const char *str, float *value) -{ - bool success = pp::numeric_lex_float(str, value); - if (!success) - *value = std::numeric_limits::max(); - return success; -} - -bool atoi_clamp(const char *str, int *value) -{ - bool success = pp::numeric_lex_int(str, value); - if (!success) - *value = std::numeric_limits::max(); - return success; -} - diff --git a/src/3rdparty/angle/src/compiler/util.h b/src/3rdparty/angle/src/compiler/util.h deleted file mode 100644 index dc69f39060..0000000000 --- a/src/3rdparty/angle/src/compiler/util.h +++ /dev/null @@ -1,20 +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. -// - -#ifndef COMPILER_UTIL_H -#define COMPILER_UTIL_H - -// atof_clamp is like atof but -// 1. it forces C locale, i.e. forcing '.' as decimal point. -// 2. it clamps the value to -FLT_MAX or FLT_MAX if overflow happens. -// Return false if overflow happens. -extern bool atof_clamp(const char *str, float *value); - -// If overflow happens, clamp the value to INT_MIN or INT_MAX. -// Return false if overflow happens. -extern bool atoi_clamp(const char *str, int *value); - -#endif // COMPILER_UTIL_H diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp index b18a876a55..e75a4b6440 100644 --- a/src/3rdparty/angle/src/libEGL/Display.cpp +++ b/src/3rdparty/angle/src/libEGL/Display.cpp @@ -1,3 +1,4 @@ +#include "../libGLESv2/precompiled.h" // // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -40,13 +41,13 @@ egl::Display *Display::getDisplay(EGLNativeDisplayType displayId) // FIXME: Check if displayId is a valid display device context - egl::Display *display = new egl::Display(displayId, (HDC)displayId); + egl::Display *display = new egl::Display(displayId); displays[displayId] = display; return display; } -Display::Display(EGLNativeDisplayType displayId, HDC deviceContext) : mDc(deviceContext) +Display::Display(EGLNativeDisplayType displayId) { mDisplayId = displayId; mRenderer = NULL; @@ -71,7 +72,7 @@ bool Display::initialize() return true; } - mRenderer = glCreateRenderer(this, mDc, mDisplayId); + mRenderer = glCreateRenderer(this, mDisplayId); if (!mRenderer) { @@ -486,7 +487,7 @@ void Display::initExtensionString() mExtensionString += "EGL_ANGLE_query_surface_pointer "; -#if !defined(ANGLE_OS_WINRT) +#if defined(ANGLE_ENABLE_D3D9) HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); if (swiftShader) { @@ -525,7 +526,7 @@ void Display::initVendorString() if (mRenderer && mRenderer->getLUID(&adapterLuid)) { char adapterLuidString[64]; - snprintf(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08l%08l)", adapterLuid.HighPart, adapterLuid.LowPart); + snprintf(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); mVendorString += adapterLuidString; } diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h index 5d55410440..cd07bb3388 100644 --- a/src/3rdparty/angle/src/libEGL/Display.h +++ b/src/3rdparty/angle/src/libEGL/Display.h @@ -11,8 +11,6 @@ #ifndef LIBEGL_DISPLAY_H_ #define LIBEGL_DISPLAY_H_ -#include "common/system.h" - #include #include @@ -65,12 +63,11 @@ class Display private: DISALLOW_COPY_AND_ASSIGN(Display); - Display(EGLNativeDisplayType displayId, HDC deviceContext); + Display(EGLNativeDisplayType displayId); bool restoreLostDevice(); EGLNativeDisplayType mDisplayId; - const HDC mDc; bool mSoftwareDevice; diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp index dbff159d0e..3443355c07 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.cpp +++ b/src/3rdparty/angle/src/libEGL/Surface.cpp @@ -1,3 +1,4 @@ +#include "../libGLESv2/precompiled.h" // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -10,6 +11,8 @@ #include +#include + #include "libEGL/Surface.h" #include "common/debug.h" @@ -20,8 +23,6 @@ #include "libEGL/main.h" #include "libEGL/Display.h" -#include - #if defined(ANGLE_OS_WINRT) #include #include @@ -118,12 +119,9 @@ bool Surface::resetSwapChain() #else ABI::Windows::Foundation::Rect windowRect; ABI::Windows::UI::Core::ICoreWindow *window; - HRESULT result = mWindow->QueryInterface(IID_PPV_ARGS(&window)); - if (FAILED(result)) - { - ASSERT(false); + HRESULT hr = mWindow->QueryInterface(IID_PPV_ARGS(&window)); + if (FAILED(hr)) return false; - } window->get_Bounds(&windowRect); width = windowRect.Width; height = windowRect.Height; @@ -156,16 +154,9 @@ bool Surface::resetSwapChain() bool Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight) { + ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); ASSERT(mSwapChain); - // Prevent bad swap chain resize by calling reset if size is invalid - if (backbufferWidth < 1 || backbufferHeight < 1) - { - mWidth = backbufferWidth; - mHeight = backbufferHeight; - return mSwapChain->reset(0, 0, mSwapInterval) == EGL_SUCCESS; - } - EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight); if (status == EGL_CONTEXT_LOST) @@ -347,18 +338,26 @@ bool Surface::checkForOutOfDateSwapChain() #else ABI::Windows::Foundation::Rect windowRect; ABI::Windows::UI::Core::ICoreWindow *window; - HRESULT result = mWindow->QueryInterface(IID_PPV_ARGS(&window)); - if (FAILED(result)) - { - ASSERT(false); + HRESULT hr = mWindow->QueryInterface(IID_PPV_ARGS(&window)); + if (FAILED(hr)) return false; - } window->get_Bounds(&windowRect); int clientWidth = windowRect.Width; int clientHeight = windowRect.Height; #endif bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); +#if !defined(ANGLE_OS_WINRT) + if (IsIconic(getWindowHandle())) + { + // The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized + // because that's not a useful size to render to. + sizeDirty = false; + } +#endif + + bool wasDirty = (mSwapIntervalDirty || sizeDirty); + if (mSwapIntervalDirty) { resetSwapChain(clientWidth, clientHeight); @@ -368,7 +367,7 @@ bool Surface::checkForOutOfDateSwapChain() resizeSwapChain(clientWidth, clientHeight); } - if (mSwapIntervalDirty || sizeDirty) + if (wasDirty) { if (static_cast(getCurrentDrawSurface()) == this) { diff --git a/src/3rdparty/angle/src/libEGL/Surface.h b/src/3rdparty/angle/src/libEGL/Surface.h index ae9a380858..1d2303c6eb 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.h +++ b/src/3rdparty/angle/src/libEGL/Surface.h @@ -15,7 +15,6 @@ #include #include "common/angleutils.h" -#include "windows.h" namespace gl { @@ -80,7 +79,7 @@ private: bool resetSwapChain(int backbufferWidth, int backbufferHeight); bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height); - const EGLNativeWindowType mWindow; // Window that the surface is created for. + const EGLNativeWindowType 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 diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp index 5bcb5d5959..b2944d5c0d 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.cpp +++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp @@ -184,7 +184,7 @@ const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name) case EGL_VENDOR: return egl::success(display->getVendorString()); case EGL_VERSION: - return egl::success("1.4 (ANGLE " VERSION_STRING ")"); + return egl::success("1.4 (ANGLE " ANGLE_VERSION_STRING ")"); } return egl::error(EGL_BAD_PARAMETER, (const char*)NULL); @@ -821,13 +821,21 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); } - if (share_context && static_cast(share_context)->isResetNotificationEnabled() != reset_notification) + gl::Context *sharedContextPtr = (share_context != EGL_NO_CONTEXT ? static_cast(share_context) : NULL); + + if (sharedContextPtr != NULL && sharedContextPtr->isResetNotificationEnabled() != reset_notification) { return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); } egl::Display *display = static_cast(dpy); + // Can not share contexts between displays + if (sharedContextPtr != NULL && sharedContextPtr->getRenderer() != display->getRenderer()) + { + return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); + } + if (!validateConfig(display, config)) { return EGL_NO_CONTEXT; diff --git a/src/3rdparty/angle/src/libEGL/libEGL.rc b/src/3rdparty/angle/src/libEGL/libEGL.rc index 5d1f32f1c9..65e0aa50c8 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.rc +++ b/src/3rdparty/angle/src/libEGL/libEGL.rc @@ -54,8 +54,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION - PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION + FILEVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0 + PRODUCTVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -71,13 +71,14 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "ANGLE libEGL Dynamic Link Library" - VALUE "FileVersion", VERSION_STRING + VALUE "FileVersion", ANGLE_VERSION_STRING VALUE "InternalName", "libEGL" VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc." VALUE "OriginalFilename", "libEGL.dll" - VALUE "PrivateBuild", VERSION_STRING + VALUE "PrivateBuild", ANGLE_VERSION_STRING VALUE "ProductName", "ANGLE libEGL Dynamic Link Library" - VALUE "ProductVersion", VERSION_STRING + VALUE "ProductVersion", ANGLE_VERSION_STRING + VALUE "Comments", "Build Date: " ANGLE_COMMIT_DATE END END BLOCK "VarFileInfo" diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp index 964b4b21fd..e972691a4f 100644 --- a/src/3rdparty/angle/src/libEGL/main.cpp +++ b/src/3rdparty/angle/src/libEGL/main.cpp @@ -11,15 +11,63 @@ #include "common/debug.h" -#ifndef QT_OPENGL_ES_2_ANGLE_STATIC - #if !defined(ANGLE_OS_WINRT) static DWORD currentTLS = TLS_OUT_OF_INDEXES; #else static __declspec(thread) void *currentTLS = 0; #endif -namespace egl { Current *getCurrent(); } +namespace egl +{ + +Current *AllocateCurrent() +{ +#if !defined(ANGLE_OS_WINRT) + Current *current = (egl::Current*)LocalAlloc(LPTR, sizeof(egl::Current)); +#else + currentTLS = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Current)); + Current *current = (egl::Current*)currentTLS; +#endif + + if (!current) + { + ERR("Could not allocate thread local storage."); + return NULL; + } + +#if !defined(ANGLE_OS_WINRT) + ASSERT(currentTLS != TLS_OUT_OF_INDEXES); + TlsSetValue(currentTLS, current); +#endif + + current->error = EGL_SUCCESS; + current->API = EGL_OPENGL_ES_API; + current->display = EGL_NO_DISPLAY; + current->drawSurface = EGL_NO_SURFACE; + current->readSurface = EGL_NO_SURFACE; + + return current; +} + +void DeallocateCurrent() +{ +#if !defined(ANGLE_OS_WINRT) + void *current = TlsGetValue(currentTLS); + + if (current) + { + LocalFree((HLOCAL)current); + } +#else + if (currentTLS) + { + HeapFree(GetProcessHeap(), 0, currentTLS); + currentTLS = 0; + } +#endif +} + +} extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { @@ -27,7 +75,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved { case DLL_PROCESS_ATTACH: { -#if !defined(ANGLE_DISABLE_TRACE) +#if defined(ANGLE_ENABLE_TRACE) FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt"); if (debug) @@ -41,7 +89,6 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved } } #endif - #if !defined(ANGLE_OS_WINRT) currentTLS = TlsAlloc(); @@ -54,51 +101,19 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved // Fall throught to initialize index case DLL_THREAD_ATTACH: { - egl::Current *current = egl::getCurrent(); - - if (current) - { -#if !defined(ANGLE_OS_WINRT) - TlsSetValue(currentTLS, current); -#endif - current->error = EGL_SUCCESS; - current->API = EGL_OPENGL_ES_API; - current->display = EGL_NO_DISPLAY; - current->drawSurface = EGL_NO_SURFACE; - current->readSurface = EGL_NO_SURFACE; - } + egl::AllocateCurrent(); } break; case DLL_THREAD_DETACH: { - egl::Current *current = egl::getCurrent(); - - if (current) - { -#if !defined(ANGLE_OS_WINRT) - LocalFree((HLOCAL)current); -#else - HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); - currentTLS = 0; -#endif - } + egl::DeallocateCurrent(); } break; case DLL_PROCESS_DETACH: { - egl::Current *current = egl::getCurrent(); - - if (current) - { + egl::DeallocateCurrent(); #if !defined(ANGLE_OS_WINRT) - LocalFree((HLOCAL)current); - } - TlsFree(currentTLS); -#else - HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); - currentTLS = 0; - } #endif } break; @@ -109,96 +124,94 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved return TRUE; } -#endif // !QT_OPENGL_ES_2_ANGLE_STATIC - namespace egl { -Current *getCurrent() + +Current *GetCurrentData() { #ifndef QT_OPENGL_ES_2_ANGLE_STATIC #if !defined(ANGLE_OS_WINRT) Current *current = (Current*)TlsGetValue(currentTLS); - if (!current) - current = (Current*)LocalAlloc(LPTR, sizeof(Current)); - return current; #else - if (!currentTLS) - currentTLS = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, sizeof(Current)); - return (Current*)currentTLS; + Current *current = (Current*)currentTLS; #endif #else // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. - static Current curr = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE }; - return &curr; + static Current s_current = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE }; + Current *current = &s_current; #endif + + // ANGLE issue 488: when the dll is loaded after thread initialization, + // thread local storage (current) might not exist yet. + return (current ? current : AllocateCurrent()); } void setCurrentError(EGLint error) { - Current *current = getCurrent(); + Current *current = GetCurrentData(); current->error = error; } EGLint getCurrentError() { - Current *current = getCurrent(); + Current *current = GetCurrentData(); return current->error; } void setCurrentAPI(EGLenum API) { - Current *current = getCurrent(); + Current *current = GetCurrentData(); current->API = API; } EGLenum getCurrentAPI() { - Current *current = getCurrent(); + Current *current = GetCurrentData(); return current->API; } void setCurrentDisplay(EGLDisplay dpy) { - Current *current = getCurrent(); + Current *current = GetCurrentData(); current->display = dpy; } EGLDisplay getCurrentDisplay() { - Current *current = getCurrent(); + Current *current = GetCurrentData(); return current->display; } void setCurrentDrawSurface(EGLSurface surface) { - Current *current = getCurrent(); + Current *current = GetCurrentData(); current->drawSurface = surface; } EGLSurface getCurrentDrawSurface() { - Current *current = getCurrent(); + Current *current = GetCurrentData(); return current->drawSurface; } void setCurrentReadSurface(EGLSurface surface) { - Current *current = getCurrent(); + Current *current = GetCurrentData(); current->readSurface = surface; } EGLSurface getCurrentReadSurface() { - Current *current = getCurrent(); + Current *current = GetCurrentData(); return current->readSurface; } diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp index 40baa95760..c007d5d9e9 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp @@ -37,11 +37,11 @@ Buffer::~Buffer() delete mStaticIndexBuffer; } -void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage, GLenum target) +void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) { mBufferStorage->clear(); mIndexRangeCache.clear(); - mBufferStorage->setData(data, size, 0, target); + mBufferStorage->setData(data, size, 0); mUsage = usage; @@ -54,9 +54,9 @@ void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage, GLenum } } -void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset, GLenum target) +void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) { - mBufferStorage->setData(data, size, offset, target); + mBufferStorage->setData(data, size, offset); mIndexRangeCache.invalidateRange(offset, size); if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)) diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.h b/src/3rdparty/angle/src/libGLESv2/Buffer.h index 9b86b9791f..4048f4b906 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Buffer.h @@ -33,8 +33,8 @@ class Buffer : public RefCountObject virtual ~Buffer(); - void bufferData(const void *data, GLsizeiptr size, GLenum usage, GLenum target); - void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset, GLenum target); + void bufferData(const void *data, GLsizeiptr size, GLenum usage); + void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset); GLenum usage() const; diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp index e829d508a6..e651785aed 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp @@ -1779,7 +1779,7 @@ void Context::applyState(GLenum drawMode) { mask = 0xFFFFFFFF; } - mRenderer->setBlendState(mState.blend, mState.blendColor, mask); + mRenderer->setBlendState(framebufferObject, mState.blend, mState.blendColor, mask); mRenderer->setDepthStencilState(mState.depthStencil, mState.stencilRef, mState.stencilBackRef, mState.rasterizer.frontFace == GL_CCW); @@ -1813,6 +1813,8 @@ void Context::applyTextures(SamplerType type) { ProgramBinary *programBinary = getCurrentProgramBinary(); + FramebufferTextureSerialSet boundFramebufferTextures = getBoundFramebufferTextureSerials(); + // Range of Direct3D samplers of given sampler type int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : mRenderer->getMaxVertexTextureImageUnits(); int samplerRange = programBinary->getUsedSamplerRange(type); @@ -1826,7 +1828,8 @@ void Context::applyTextures(SamplerType type) TextureType textureType = programBinary->getSamplerTextureType(type, samplerIndex); Texture *texture = getSamplerTexture(textureUnit, textureType); - if (texture->isSamplerComplete()) + if (texture->isSamplerComplete() && + boundFramebufferTextures.find(texture->getTextureSerial()) == boundFramebufferTextures.end()) { SamplerState samplerState; texture->getSamplerState(&samplerState); @@ -2656,6 +2659,29 @@ const char *Context::getRendererString() const return mRendererString; } +Context::FramebufferTextureSerialSet Context::getBoundFramebufferTextureSerials() +{ + FramebufferTextureSerialSet set; + + Framebuffer *drawFramebuffer = getDrawFramebuffer(); + for (unsigned int i = 0; i < IMPLEMENTATION_MAX_DRAW_BUFFERS; i++) + { + Renderbuffer *renderBuffer = drawFramebuffer->getColorbuffer(i); + if (renderBuffer && renderBuffer->getTextureSerial() != 0) + { + set.insert(renderBuffer->getTextureSerial()); + } + } + + Renderbuffer *depthStencilBuffer = drawFramebuffer->getDepthOrStencilbuffer(); + if (depthStencilBuffer && depthStencilBuffer->getTextureSerial() != 0) + { + set.insert(depthStencilBuffer->getTextureSerial()); + } + + return set; +} + void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask) diff --git a/src/3rdparty/angle/src/libGLESv2/Context.h b/src/3rdparty/angle/src/libGLESv2/Context.h index 9c222be24d..3dc95e3b95 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.h +++ b/src/3rdparty/angle/src/libGLESv2/Context.h @@ -18,6 +18,7 @@ #include #include +#include #ifdef _MSC_VER #include #else @@ -37,7 +38,6 @@ class Renderer; namespace egl { -class Display; class Surface; } @@ -73,7 +73,7 @@ enum QueryType class VertexAttribute { public: - VertexAttribute() : mType(GL_FLOAT), mSize(0), mNormalized(false), mStride(0), mPointer(NULL), mArrayEnabled(false), mDivisor(0) + VertexAttribute() : mType(GL_FLOAT), mSize(4), mNormalized(false), mStride(0), mPointer(NULL), mArrayEnabled(false), mDivisor(0) { mCurrentValue[0] = 0.0f; mCurrentValue[1] = 0.0f; @@ -398,6 +398,8 @@ class Context GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask); + rx::Renderer *getRenderer() { return mRenderer; } + private: DISALLOW_COPY_AND_ASSIGN(Context); @@ -419,6 +421,9 @@ class Context void initExtensionString(); void initRendererString(); + typedef std::set FramebufferTextureSerialSet; + FramebufferTextureSerialSet getBoundFramebufferTextureSerials(); + rx::Renderer *const mRenderer; State mState; diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h index b54e008dd8..50bfd4fd0f 100644 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h @@ -12,7 +12,7 @@ #include "common/angleutils.h" #include "common/RefCountObject.h" -#include "constants.h" +#include "Constants.h" namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp index bcd04b7157..a4d21192fa 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp @@ -34,6 +34,11 @@ std::string str(int i) return buffer; } +static rx::D3DWorkaroundType DiscardWorkaround(bool usesDiscard) +{ + return (usesDiscard ? rx::ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER : rx::ANGLE_D3D_WORKAROUND_NONE); +} + UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index) : name(name), element(element), index(index) { @@ -1622,9 +1627,19 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) return false; } - int version = 0; - stream.read(&version); - if (version != VERSION_DWORD) + int majorVersion = 0; + int minorVersion = 0; + stream.read(&majorVersion); + stream.read(&minorVersion); + if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION) + { + infoLog.append("Invalid program binary version."); + return false; + } + + unsigned char commitString[ANGLE_COMMIT_HASH_SIZE]; + stream.read(commitString, ANGLE_COMMIT_HASH_SIZE); + if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0) { infoLog.append("Invalid program binary version."); return false; @@ -1791,7 +1806,9 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) BinaryOutputStream stream; stream.write(GL_PROGRAM_BINARY_ANGLE); - stream.write(VERSION_DWORD); + stream.write(ANGLE_MAJOR_VERSION); + stream.write(ANGLE_MINOR_VERSION); + stream.write(ANGLE_COMMIT_HASH, ANGLE_COMMIT_HASH_SIZE); stream.write(ANGLE_COMPILE_OPTIMIZATION_LEVEL); for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) @@ -1962,13 +1979,13 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin if (success) { - mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX); - mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL); + mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX, DiscardWorkaround(vertexShader->mUsesDiscardRewriting)); + mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL, DiscardWorkaround(fragmentShader->mUsesDiscardRewriting)); if (usesGeometryShader()) { std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader); - mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY); + mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY, rx::ANGLE_D3D_WORKAROUND_NONE); } if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable)) @@ -2587,7 +2604,9 @@ struct AttributeSorter bool operator()(int a, int b) { - return originalIndices[a] == -1 ? false : originalIndices[a] < originalIndices[b]; + if (originalIndices[a] == -1) return false; + if (originalIndices[b] == -1) return true; + return (originalIndices[a] < originalIndices[b]); } const int (&originalIndices)[MAX_VERTEX_ATTRIBS]; @@ -2615,7 +2634,7 @@ void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MA for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) { int oldIndex = mAttributesByLayout[i]; - sortedSemanticIndices[i] = mSemanticIndex[oldIndex]; + sortedSemanticIndices[i] = oldIndex; attributes[i] = oldTranslatedAttributes[oldIndex]; } } diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp index 127513741c..98d33ec6c3 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp @@ -129,6 +129,11 @@ unsigned int RenderbufferTexture2D::getSerial() const return mTexture2D->getRenderTargetSerial(mTarget); } +unsigned int RenderbufferTexture2D::getTextureSerial() const +{ + return mTexture2D->getTextureSerial(); +} + ///// RenderbufferTextureCubeMap Implementation //////// RenderbufferTextureCubeMap::RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target) : mTarget(target) @@ -193,6 +198,11 @@ unsigned int RenderbufferTextureCubeMap::getSerial() const return mTextureCubeMap->getRenderTargetSerial(mTarget); } +unsigned int RenderbufferTextureCubeMap::getTextureSerial() const +{ + return mTextureCubeMap->getTextureSerial(); +} + ////// Renderbuffer Implementation ////// Renderbuffer::Renderbuffer(rx::Renderer *renderer, GLuint id, RenderbufferInterface *instance) : RefCountObject(id) @@ -292,6 +302,11 @@ unsigned int Renderbuffer::getSerial() const return mInstance->getSerial(); } +unsigned int Renderbuffer::getTextureSerial() const +{ + return mInstance->getTextureSerial(); +} + void Renderbuffer::setStorage(RenderbufferStorage *newStorage) { ASSERT(newStorage != NULL); diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h index eca2f3a780..d46fd44557 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h @@ -60,6 +60,7 @@ class RenderbufferInterface GLuint getStencilSize() const; virtual unsigned int getSerial() const = 0; + virtual unsigned int getTextureSerial() const = 0; private: DISALLOW_COPY_AND_ASSIGN(RenderbufferInterface); @@ -85,6 +86,7 @@ class RenderbufferTexture2D : public RenderbufferInterface virtual GLsizei getSamples() const; virtual unsigned int getSerial() const; + virtual unsigned int getTextureSerial() const; private: DISALLOW_COPY_AND_ASSIGN(RenderbufferTexture2D); @@ -113,6 +115,7 @@ class RenderbufferTextureCubeMap : public RenderbufferInterface virtual GLsizei getSamples() const; virtual unsigned int getSerial() const; + virtual unsigned int getTextureSerial() const; private: DISALLOW_COPY_AND_ASSIGN(RenderbufferTextureCubeMap); @@ -141,6 +144,7 @@ class RenderbufferStorage : public RenderbufferInterface virtual GLsizei getSamples() const; virtual unsigned int getSerial() const; + virtual unsigned int getTextureSerial() const { return 0; } static unsigned int issueSerial(); static unsigned int issueCubeSerials(); @@ -193,6 +197,7 @@ class Renderbuffer : public RefCountObject GLsizei getSamples() const; unsigned int getSerial() const; + unsigned int getTextureSerial() const; void setStorage(RenderbufferStorage *newStorage); diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp index 7dfdd0ba3a..f6a2f03dfc 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Shader.cpp @@ -307,6 +307,7 @@ void Shader::parseVaryings() mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL; mUsesDepthRange = strstr(mHlsl, "GL_USES_DEPTH_RANGE") != NULL; mUsesFragDepth = strstr(mHlsl, "GL_USES_FRAG_DEPTH") != NULL; + mUsesDiscardRewriting = strstr(mHlsl, "ANGLE_USES_DISCARD_REWRITING") != NULL; } } @@ -340,6 +341,7 @@ void Shader::uncompile() mUsesPointCoord = false; mUsesDepthRange = false; mUsesFragDepth = false; + mUsesDiscardRewriting = false; mActiveUniforms.clear(); } diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.h b/src/3rdparty/angle/src/libGLESv2/Shader.h index 2afe2976c3..2015addd11 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.h +++ b/src/3rdparty/angle/src/libGLESv2/Shader.h @@ -18,7 +18,7 @@ #include #include -#include "compiler/Uniform.h" +#include "compiler/translator/Uniform.h" #include "common/angleutils.h" namespace rx @@ -107,6 +107,7 @@ class Shader bool mUsesPointCoord; bool mUsesDepthRange; bool mUsesFragDepth; + bool mUsesDiscardRewriting; static void *mFragmentCompiler; static void *mVertexCompiler; diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp index 72c0a8ab79..3257d05dd4 100644 --- a/src/3rdparty/angle/src/libGLESv2/Texture.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Texture.cpp @@ -14,8 +14,8 @@ #include "libGLESv2/main.h" #include "libGLESv2/mathutil.h" #include "libGLESv2/utilities.h" -#ifndef ANGLE_ENABLE_D3D11 -# include "libGLESv2/renderer/Blit.h" +#if defined(ANGLE_ENABLE_D3D9) +# include "libGLESv2/renderer/d3d9/Blit.h" #else # define D3DFMT_UNKNOWN DXGI_FORMAT_UNKNOWN #endif @@ -1362,10 +1362,10 @@ void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size for (int level = 0; level < levels; level++) { + GLsizei mipSize = std::max(1, size >> level); for (int face = 0; face < 6; face++) { - mImageArray[face][level]->redefine(mRenderer, internalformat, size, size, true); - size = std::max(1, size >> 1); + mImageArray[face][level]->redefine(mRenderer, internalformat, mipSize, mipSize, true); } } diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp index 91719f8e6d..814dfbf965 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp @@ -758,7 +758,7 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, return gl::error(GL_INVALID_OPERATION); } - buffer->bufferData(data, size, usage, target); + buffer->bufferData(data, size, usage); } } catch(std::bad_alloc&) @@ -812,7 +812,7 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, return gl::error(GL_INVALID_VALUE); } - buffer->bufferSubData(data, size, offset, target); + buffer->bufferSubData(data, size, offset); } } catch(std::bad_alloc&) @@ -3844,9 +3844,9 @@ const GLubyte* __stdcall glGetString(GLenum name) case GL_RENDERER: return (GLubyte*)((context != NULL) ? context->getRendererString() : "ANGLE"); case GL_VERSION: - return (GLubyte*)"OpenGL ES 2.0 (ANGLE " VERSION_STRING ")"; + return (GLubyte*)"OpenGL ES 2.0 (ANGLE " ANGLE_VERSION_STRING ")"; case GL_SHADING_LANGUAGE_VERSION: - return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " VERSION_STRING ")"; + return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " ANGLE_VERSION_STRING ")"; case GL_EXTENSIONS: return (GLubyte*)((context != NULL) ? context->getExtensionString() : ""); default: @@ -4893,9 +4893,9 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp case GL_RGB565: case GL_RGB8_OES: case GL_RGBA8_OES: - case GL_BGRA8_EXT: case GL_STENCIL_INDEX8: case GL_DEPTH24_STENCIL8_OES: + case GL_BGRA8_EXT: context->setRenderbufferStorage(width, height, internalformat, samples); break; default: diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc b/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc index 0ad21e440e..76cd05566e 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc @@ -54,8 +54,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION - PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION + FILEVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0 + PRODUCTVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -71,13 +71,14 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "ANGLE libGLESv2 Dynamic Link Library" - VALUE "FileVersion", VERSION_STRING + VALUE "FileVersion", ANGLE_VERSION_STRING VALUE "InternalName", "libGLESv2" VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc." VALUE "OriginalFilename", "libGLESv2.dll" - VALUE "PrivateBuild", VERSION_STRING + VALUE "PrivateBuild", ANGLE_VERSION_STRING VALUE "ProductName", "ANGLE libGLESv2 Dynamic Link Library" - VALUE "ProductVersion", VERSION_STRING + VALUE "ProductVersion", ANGLE_VERSION_STRING + VALUE "Comments", "Build Date: " ANGLE_COMMIT_DATE END END BLOCK "VarFileInfo" diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp index defdf35f77..95f4b8de1c 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.cpp +++ b/src/3rdparty/angle/src/libGLESv2/main.cpp @@ -11,15 +11,60 @@ #include "libGLESv2/Context.h" -#ifndef QT_OPENGL_ES_2_ANGLE_STATIC - #if !defined(ANGLE_OS_WINRT) static DWORD currentTLS = TLS_OUT_OF_INDEXES; #else static __declspec(thread) void *currentTLS = 0; #endif -namespace gl { Current *getCurrent(); } +namespace gl +{ + +Current *AllocateCurrent() +{ +#if !defined(ANGLE_OS_WINRT) + Current *current = (Current*)LocalAlloc(LPTR, sizeof(Current)); +#else + currentTLS = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Current)); + Current *current = (Current*)currentTLS; +#endif + + if (!current) + { + ERR("Could not allocate thread local storage."); + return NULL; + } + +#if !defined(ANGLE_OS_WINRT) + ASSERT(currentTLS != TLS_OUT_OF_INDEXES); + TlsSetValue(currentTLS, current); +#endif + + current->context = NULL; + current->display = NULL; + + return current; +} + +void DeallocateCurrent() +{ +#if !defined(ANGLE_OS_WINRT) + void *current = TlsGetValue(currentTLS); + + if (current) + { + LocalFree((HLOCAL)current); + } +#else + if (currentTLS) + { + HeapFree(GetProcessHeap(), 0, currentTLS); + currentTLS = 0; + } +#endif +} + +} extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { @@ -39,48 +84,19 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved // Fall throught to initialize index case DLL_THREAD_ATTACH: { - gl::Current *current = gl::getCurrent(); - - if (current) - { -#if !defined(ANGLE_OS_WINRT) - TlsSetValue(currentTLS, current); -#endif - current->context = NULL; - current->display = NULL; - } + gl::AllocateCurrent(); } break; case DLL_THREAD_DETACH: { - gl::Current *current = gl::getCurrent(); - - if (current) - { -#if !defined(ANGLE_OS_WINRT) - LocalFree((HLOCAL)current); -#else - HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); - currentTLS = 0; -#endif - } + gl::DeallocateCurrent(); } break; case DLL_PROCESS_DETACH: { - gl::Current *current = gl::getCurrent(); - - if (current) - { + gl::DeallocateCurrent(); #if !defined(ANGLE_OS_WINRT) - LocalFree((HLOCAL)current); - } - TlsFree(currentTLS); -#else - HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); - currentTLS = 0; - } #endif } break; @@ -91,33 +107,31 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved return TRUE; } -#endif // !QT_OPENGL_ES_2_ANGLE_STATIC - namespace gl { -Current *getCurrent() + +Current *GetCurrentData() { #ifndef QT_OPENGL_ES_2_ANGLE_STATIC #if !defined(ANGLE_OS_WINRT) Current *current = (Current*)TlsGetValue(currentTLS); - if (!current) - current = (Current*)LocalAlloc(LPTR, sizeof(Current)); - return current; #else - if (!currentTLS) - currentTLS = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, sizeof(Current)); - return (Current*)currentTLS; + Current *current = (Current*)currentTLS; #endif #else // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. - static gl::Current curr = { 0, 0 }; - return &curr; + static Current s_current = { 0, 0 }; + Current *current = &s_current; #endif + + // ANGLE issue 488: when the dll is loaded after thread initialization, + // thread local storage (current) might not exist yet. + return (current ? current : AllocateCurrent()); } void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) { - Current *current = getCurrent(); + Current *current = GetCurrentData(); current->context = context; current->display = display; @@ -130,7 +144,7 @@ void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) Context *getContext() { - Current *current = getCurrent(); + Current *current = GetCurrentData(); return current->context; } @@ -156,7 +170,7 @@ Context *getNonLostContext() egl::Display *getDisplay() { - Current *current = getCurrent(); + Current *current = GetCurrentData(); return current->display; } diff --git a/src/3rdparty/angle/src/libGLESv2/main.h b/src/3rdparty/angle/src/libGLESv2/main.h index 196afaeab6..69465c9bbf 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.h +++ b/src/3rdparty/angle/src/libGLESv2/main.h @@ -10,7 +10,6 @@ #define LIBGLESV2_MAIN_H_ #include "common/debug.h" -#include "common/system.h" namespace egl { @@ -58,7 +57,7 @@ gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *rend void glDestroyContext(gl::Context *context); void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface); gl::Context *glGetCurrentContext(); -rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayType displayId); +rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType displayId); void glDestroyRenderer(rx::Renderer *renderer); __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname); diff --git a/src/3rdparty/angle/src/libGLESv2/mathutil.h b/src/3rdparty/angle/src/libGLESv2/mathutil.h index 083548669a..6474b66745 100644 --- a/src/3rdparty/angle/src/libGLESv2/mathutil.h +++ b/src/3rdparty/angle/src/libGLESv2/mathutil.h @@ -11,7 +11,6 @@ #include -#include "common/system.h" #include "common/debug.h" namespace gl diff --git a/src/3rdparty/angle/src/libGLESv2/precompiled.h b/src/3rdparty/angle/src/libGLESv2/precompiled.h index 823d27bb60..2ff09f531e 100644 --- a/src/3rdparty/angle/src/libGLESv2/precompiled.h +++ b/src/3rdparty/angle/src/libGLESv2/precompiled.h @@ -33,26 +33,53 @@ #include #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) -#define ANGLE_OS_WINRT -#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP -#define ANGLE_OS_WINPHONE +# define ANGLE_OS_WINRT +# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP +# define ANGLE_OS_WINPHONE +# endif #endif + +#if defined(ANGLE_ENABLE_D3D9) +# include +#endif +#if defined(ANGLE_ENABLE_D3D11) +# if !defined(ANGLE_OS_WINRT) +# include +# else +# include +# define Sleep(x) WaitForSingleObjectEx(GetCurrentThread(), x, FALSE) +# define GetVersion() WINVER +# define LoadLibrary(x) LoadPackagedLibrary(x, NULL) +# endif +# include +#endif +#if !defined(ANGLE_OS_WINPHONE) +# include #endif -#ifndef ANGLE_ENABLE_D3D11 -#include -#else -#if !defined(ANGLE_OS_WINRT) -#include -#else -#include -#define Sleep(x) WaitForSingleObjectEx(GetCurrentThread(), x, FALSE) -#define GetVersion() WINVER +#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL0 +#define D3DCOMPILE_OPTIMIZATION_LEVEL0 (1 << 14) +#endif +#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL1 +#define D3DCOMPILE_OPTIMIZATION_LEVEL1 0 +#endif +#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL2 +#define D3DCOMPILE_OPTIMIZATION_LEVEL2 ((1 << 14) | (1 << 15)) +#endif +#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL3 +#define D3DCOMPILE_OPTIMIZATION_LEVEL3 (1 << 15) +#endif +#ifndef D3DCOMPILE_DEBUG +#define D3DCOMPILE_DEBUG (1 << 0) +#endif +#ifndef D3DCOMPILE_SKIP_OPTIMIZATION +#define D3DCOMPILE_SKIP_OPTIMIZATION (1 << 2) #endif -#include +#ifndef D3DCOMPILE_AVOID_FLOW_CONTROL +#define D3DCOMPILE_AVOID_FLOW_CONTROL (1 << 9) #endif -#ifndef ANGLE_OS_WINPHONE -#include +#ifndef D3DCOMPILE_PREFER_FLOW_CONTROL +#define D3DCOMPILE_PREFER_FLOW_CONTROL (1 << 10) #endif #ifdef _MSC_VER diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Blit.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Blit.cpp deleted file mode 100644 index 2a3ce39c63..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Blit.cpp +++ /dev/null @@ -1,595 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Blit.cpp: Surface copy utility class. - -#include "libGLESv2/renderer/Blit.h" - -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/renderer9_utils.h" -#include "libGLESv2/renderer/TextureStorage9.h" -#include "libGLESv2/renderer/RenderTarget9.h" -#include "libGLESv2/renderer/Renderer9.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" - -namespace -{ -#include "libGLESv2/renderer/shaders/compiled/standardvs.h" -#include "libGLESv2/renderer/shaders/compiled/flipyvs.h" -#include "libGLESv2/renderer/shaders/compiled/passthroughps.h" -#include "libGLESv2/renderer/shaders/compiled/luminanceps.h" -#include "libGLESv2/renderer/shaders/compiled/componentmaskps.h" - -const BYTE* const g_shaderCode[] = -{ - g_vs20_standardvs, - g_vs20_flipyvs, - g_ps20_passthroughps, - g_ps20_luminanceps, - g_ps20_componentmaskps -}; - -const size_t g_shaderSize[] = -{ - sizeof(g_vs20_standardvs), - sizeof(g_vs20_flipyvs), - sizeof(g_ps20_passthroughps), - sizeof(g_ps20_luminanceps), - sizeof(g_ps20_componentmaskps) -}; -} - -namespace rx -{ -Blit::Blit(rx::Renderer9 *renderer) - : mRenderer(renderer), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedStateBlock(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL) -{ - initGeometry(); - memset(mCompiledShaders, 0, sizeof(mCompiledShaders)); -} - -Blit::~Blit() -{ - if (mSavedStateBlock) mSavedStateBlock->Release(); - if (mQuadVertexBuffer) mQuadVertexBuffer->Release(); - if (mQuadVertexDeclaration) mQuadVertexDeclaration->Release(); - - for (int i = 0; i < SHADER_COUNT; i++) - { - if (mCompiledShaders[i]) - { - mCompiledShaders[i]->Release(); - } - } -} - -void Blit::initGeometry() -{ - static const float quad[] = - { - -1, -1, - -1, 1, - 1, -1, - 1, 1 - }; - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::error(GL_OUT_OF_MEMORY); - } - - void *lockPtr = NULL; - result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0); - - if (FAILED(result) || lockPtr == NULL) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::error(GL_OUT_OF_MEMORY); - } - - memcpy(lockPtr, quad, sizeof(quad)); - mQuadVertexBuffer->Unlock(); - - static const D3DVERTEXELEMENT9 elements[] = - { - { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, - D3DDECL_END() - }; - - result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::error(GL_OUT_OF_MEMORY); - } -} - -template -bool Blit::setShader(ShaderId source, const char *profile, - D3DShaderType *(rx::Renderer9::*createShader)(const DWORD *, size_t length), - HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)) -{ - IDirect3DDevice9 *device = mRenderer->getDevice(); - - D3DShaderType *shader; - - if (mCompiledShaders[source] != NULL) - { - shader = static_cast(mCompiledShaders[source]); - } - else - { - const BYTE* shaderCode = g_shaderCode[source]; - size_t shaderSize = g_shaderSize[source]; - - shader = (mRenderer->*createShader)(reinterpret_cast(shaderCode), shaderSize); - if (!shader) - { - ERR("Failed to create shader for blit operation"); - return false; - } - - mCompiledShaders[source] = shader; - } - - HRESULT hr = (device->*setShader)(shader); - - if (FAILED(hr)) - { - ERR("Failed to set shader for blit operation"); - return false; - } - - return true; -} - -bool Blit::setVertexShader(ShaderId shader) -{ - return setShader(shader, "vs_2_0", &rx::Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader); -} - -bool Blit::setPixelShader(ShaderId shader) -{ - return setShader(shader, "ps_2_0", &rx::Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader); -} - -RECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const -{ - D3DSURFACE_DESC desc; - surface->GetDesc(&desc); - - RECT rect; - rect.left = 0; - rect.top = 0; - rect.right = desc.Width; - rect.bottom = desc.Height; - - return rect; -} - -bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) -{ - IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source)); - if (!texture) - { - return false; - } - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - saveState(); - - device->SetTexture(0, texture); - device->SetRenderTarget(0, dest); - - setVertexShader(SHADER_VS_STANDARD); - setPixelShader(SHADER_PS_PASSTHROUGH); - - setCommonBlitState(); - device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - - setViewport(getSurfaceRect(dest), 0, 0); - - render(); - - texture->Release(); - - restoreState(); - - return true; -} - -bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) -{ - RenderTarget9 *renderTarget = NULL; - IDirect3DSurface9 *source = NULL; - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); - - if (colorbuffer) - { - renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); - } - - if (renderTarget) - { - source = renderTarget->getSurface(); - } - - if (!source) - { - ERR("Failed to retrieve the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); - IDirect3DSurface9 *destSurface = storage9->getSurfaceLevel(level, true); - bool result = false; - - if (destSurface) - { - result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); - destSurface->Release(); - } - - source->Release(); - return result; -} - -bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) -{ - RenderTarget9 *renderTarget = NULL; - IDirect3DSurface9 *source = NULL; - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); - - if (colorbuffer) - { - renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); - } - - if (renderTarget) - { - source = renderTarget->getSurface(); - } - - if (!source) - { - ERR("Failed to retrieve the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); - IDirect3DSurface9 *destSurface = storage9->getCubeMapSurface(target, level, true); - bool result = false; - - if (destSurface) - { - result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); - destSurface->Release(); - } - - source->Release(); - return result; -} - -bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) -{ - if (!dest) - { - return false; - } - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - D3DSURFACE_DESC sourceDesc; - D3DSURFACE_DESC destDesc; - source->GetDesc(&sourceDesc); - dest->GetDesc(&destDesc); - - if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET && - d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect - { - RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)}; - HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::error(GL_OUT_OF_MEMORY, false); - } - } - else - { - return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest); - } - return true; -} - -bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) -{ - IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect); - if (!texture) - { - return false; - } - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - saveState(); - - device->SetTexture(0, texture); - device->SetRenderTarget(0, dest); - - setViewport(sourceRect, xoffset, yoffset); - - setCommonBlitState(); - if (setFormatConvertShaders(destFormat)) - { - render(); - } - - texture->Release(); - - restoreState(); - - return true; -} - -bool Blit::setFormatConvertShaders(GLenum destFormat) -{ - bool okay = setVertexShader(SHADER_VS_STANDARD); - - switch (destFormat) - { - default: UNREACHABLE(); - case GL_RGBA: - case GL_BGRA_EXT: - case GL_RGB: - case GL_ALPHA: - okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK); - break; - - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - okay = okay && setPixelShader(SHADER_PS_LUMINANCE); - break; - } - - if (!okay) - { - return false; - } - - enum { X = 0, Y = 1, Z = 2, W = 3 }; - - // The meaning of this constant depends on the shader that was selected. - // See the shader assembly code above for details. - float psConst0[4] = { 0, 0, 0, 0 }; - - switch (destFormat) - { - default: UNREACHABLE(); - case GL_RGBA: - case GL_BGRA_EXT: - psConst0[X] = 1; - psConst0[Z] = 1; - break; - - case GL_RGB: - psConst0[X] = 1; - psConst0[W] = 1; - break; - - case GL_ALPHA: - psConst0[Z] = 1; - break; - - case GL_LUMINANCE: - psConst0[Y] = 1; - break; - - case GL_LUMINANCE_ALPHA: - psConst0[X] = 1; - break; - } - - mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst0, 1); - - return true; -} - -IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect) -{ - if (!surface) - { - return NULL; - } - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - D3DSURFACE_DESC sourceDesc; - surface->GetDesc(&sourceDesc); - - // Copy the render target into a texture - IDirect3DTexture9 *texture; - HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); - } - - IDirect3DSurface9 *textureSurface; - result = texture->GetSurfaceLevel(0, &textureSurface); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - texture->Release(); - return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); - } - - mRenderer->endScene(); - result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE); - - textureSurface->Release(); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - texture->Release(); - return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); - } - - return texture; -} - -void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset) -{ - IDirect3DDevice9 *device = mRenderer->getDevice(); - - D3DVIEWPORT9 vp; - vp.X = xoffset; - vp.Y = yoffset; - vp.Width = sourceRect.right - sourceRect.left; - vp.Height = sourceRect.bottom - sourceRect.top; - vp.MinZ = 0.0f; - vp.MaxZ = 1.0f; - device->SetViewport(&vp); - - float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 }; - device->SetVertexShaderConstantF(0, halfPixelAdjust, 1); -} - -void Blit::setCommonBlitState() -{ - IDirect3DDevice9 *device = mRenderer->getDevice(); - - device->SetDepthStencilSurface(NULL); - - device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); - device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); - device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); - - device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE); - device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - - RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle - device->SetScissorRect(&scissorRect); - - for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - device->SetStreamSourceFreq(i, 1); - } -} - -void Blit::render() -{ - IDirect3DDevice9 *device = mRenderer->getDevice(); - - HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float)); - hr = device->SetVertexDeclaration(mQuadVertexDeclaration); - - mRenderer->startScene(); - hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); -} - -void Blit::saveState() -{ - IDirect3DDevice9 *device = mRenderer->getDevice(); - - HRESULT hr; - - device->GetDepthStencilSurface(&mSavedDepthStencil); - device->GetRenderTarget(0, &mSavedRenderTarget); - - if (mSavedStateBlock == NULL) - { - hr = device->BeginStateBlock(); - ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); - - setCommonBlitState(); - - static const float dummyConst[4] = { 0, 0, 0, 0 }; - - device->SetVertexShader(NULL); - device->SetVertexShaderConstantF(0, dummyConst, 1); - device->SetPixelShader(NULL); - device->SetPixelShaderConstantF(0, dummyConst, 1); - - D3DVIEWPORT9 dummyVp; - dummyVp.X = 0; - dummyVp.Y = 0; - dummyVp.Width = 1; - dummyVp.Height = 1; - dummyVp.MinZ = 0; - dummyVp.MaxZ = 1; - - device->SetViewport(&dummyVp); - - device->SetTexture(0, NULL); - - device->SetStreamSource(0, mQuadVertexBuffer, 0, 0); - - device->SetVertexDeclaration(mQuadVertexDeclaration); - - hr = device->EndStateBlock(&mSavedStateBlock); - ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); - } - - ASSERT(mSavedStateBlock != NULL); - - if (mSavedStateBlock != NULL) - { - hr = mSavedStateBlock->Capture(); - ASSERT(SUCCEEDED(hr)); - } -} - -void Blit::restoreState() -{ - IDirect3DDevice9 *device = mRenderer->getDevice(); - - device->SetDepthStencilSurface(mSavedDepthStencil); - if (mSavedDepthStencil != NULL) - { - mSavedDepthStencil->Release(); - mSavedDepthStencil = NULL; - } - - device->SetRenderTarget(0, mSavedRenderTarget); - if (mSavedRenderTarget != NULL) - { - mSavedRenderTarget->Release(); - mSavedRenderTarget = NULL; - } - - ASSERT(mSavedStateBlock != NULL); - - if (mSavedStateBlock != NULL) - { - mSavedStateBlock->Apply(); - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Blit.h b/src/3rdparty/angle/src/libGLESv2/renderer/Blit.h deleted file mode 100644 index 3718028e66..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Blit.h +++ /dev/null @@ -1,94 +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. -// - -// Blit.cpp: Surface copy utility class. - -#ifndef LIBGLESV2_BLIT_H_ -#define LIBGLESV2_BLIT_H_ - -#include "common/angleutils.h" - -namespace gl -{ -class Framebuffer; -} - -namespace rx -{ -class Renderer9; -class TextureStorageInterface2D; -class TextureStorageInterfaceCube; - -class Blit -{ - public: - explicit Blit(Renderer9 *renderer); - ~Blit(); - - // Copy from source surface to dest surface. - // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) - bool copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level); - bool copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level); - - // Copy from source surface to dest surface. - // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) - // source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0. - bool formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); - - // 2x2 box filter sample from source to dest. - // Requires that source is RGB(A) and dest has the same format as source. - bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); - - private: - rx::Renderer9 *mRenderer; - - IDirect3DVertexBuffer9 *mQuadVertexBuffer; - IDirect3DVertexDeclaration9 *mQuadVertexDeclaration; - - void initGeometry(); - - bool setFormatConvertShaders(GLenum destFormat); - - bool copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); - IDirect3DTexture9 *copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect); - void setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset); - void setCommonBlitState(); - RECT getSurfaceRect(IDirect3DSurface9 *surface) const; - - // This enum is used to index mCompiledShaders and mShaderSource. - enum ShaderId - { - SHADER_VS_STANDARD, - SHADER_VS_FLIPY, - SHADER_PS_PASSTHROUGH, - SHADER_PS_LUMINANCE, - SHADER_PS_COMPONENTMASK, - SHADER_COUNT - }; - - // This actually contains IDirect3DVertexShader9 or IDirect3DPixelShader9 casted to IUnknown. - IUnknown *mCompiledShaders[SHADER_COUNT]; - - template - bool setShader(ShaderId source, const char *profile, - D3DShaderType *(Renderer9::*createShader)(const DWORD *, size_t length), - HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)); - - bool setVertexShader(ShaderId shader); - bool setPixelShader(ShaderId shader); - void render(); - - void saveState(); - void restoreState(); - IDirect3DStateBlock9 *mSavedStateBlock; - IDirect3DSurface9 *mSavedRenderTarget; - IDirect3DSurface9 *mSavedDepthStencil; - - DISALLOW_COPY_AND_ASSIGN(Blit); -}; -} - -#endif // LIBGLESV2_BLIT_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h index 14a8c2765b..ace1a11bae 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h @@ -22,7 +22,7 @@ class BufferStorage // The data returned is only guaranteed valid until next non-const method. virtual void *getData() = 0; - virtual void setData(const void* data, unsigned int size, unsigned int offset, unsigned int target) = 0; + virtual void setData(const void* data, unsigned int size, unsigned int offset) = 0; virtual void clear() = 0; virtual unsigned int getSize() const = 0; virtual bool supportsDirectBinding() const = 0; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp deleted file mode 100644 index 2f694db061..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp +++ /dev/null @@ -1,361 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BufferStorage11.cpp Defines the BufferStorage11 class. - -#include "libGLESv2/renderer/BufferStorage11.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/Renderer11.h" - -namespace rx -{ - -BufferStorage11::BufferStorage11(Renderer11 *renderer) -{ - mRenderer = renderer; - - mStagingBuffer = NULL; - mStagingBufferSize = 0; - - mBuffer = NULL; - mBufferSize = 0; - - mSize = 0; - - mResolvedData = NULL; - mResolvedDataSize = 0; - mResolvedDataValid = false; - - mReadUsageCount = 0; - mWriteUsageCount = 0; -} - -BufferStorage11::~BufferStorage11() -{ - if (mStagingBuffer) - { - mStagingBuffer->Release(); - mStagingBuffer = NULL; - } - - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - } - - if (mResolvedData) - { - free(mResolvedData); - mResolvedData = NULL; - } -} - -BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage) -{ - ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage)); - return static_cast(bufferStorage); -} - -void *BufferStorage11::getData() -{ - if (!mResolvedDataValid) - { - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - HRESULT result; - - if (!mStagingBuffer || mStagingBufferSize < mBufferSize) - { - if (mStagingBuffer) - { - mStagingBuffer->Release(); - mStagingBuffer = NULL; - mStagingBufferSize = 0; - } - - D3D11_BUFFER_DESC bufferDesc; - bufferDesc.ByteWidth = mSize; - bufferDesc.Usage = D3D11_USAGE_STAGING; - bufferDesc.BindFlags = 0; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - bufferDesc.MiscFlags = 0; - bufferDesc.StructureByteStride = 0; - - result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer); - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); - } - - mStagingBufferSize = bufferDesc.ByteWidth; - } - - if (!mResolvedData || mResolvedDataSize < mBufferSize) - { - free(mResolvedData); - mResolvedData = malloc(mSize); - mResolvedDataSize = mSize; - } - - D3D11_BOX srcBox; - srcBox.left = 0; - srcBox.right = mSize; - srcBox.top = 0; - srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; - - context->CopySubresourceRegion(mStagingBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource); - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); - } - - memcpy(mResolvedData, mappedResource.pData, mSize); - - context->Unmap(mStagingBuffer, 0); - - mResolvedDataValid = true; - } - - mReadUsageCount = 0; - - return mResolvedData; -} - -void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset, unsigned int target) -{ - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - HRESULT result; - - unsigned int requiredBufferSize = size + offset; - unsigned int requiredStagingSize = size; - bool directInitialization = offset == 0 && (!mBuffer || mBufferSize < size + offset); - - if (!directInitialization) - { - if (!mStagingBuffer || mStagingBufferSize < requiredStagingSize) - { - if (mStagingBuffer) - { - mStagingBuffer->Release(); - mStagingBuffer = NULL; - mStagingBufferSize = 0; - } - - D3D11_BUFFER_DESC bufferDesc; - bufferDesc.ByteWidth = size; - bufferDesc.Usage = D3D11_USAGE_STAGING; - bufferDesc.BindFlags = 0; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - bufferDesc.MiscFlags = 0; - bufferDesc.StructureByteStride = 0; - - if (data) - { - D3D11_SUBRESOURCE_DATA initialData; - initialData.pSysMem = data; - initialData.SysMemPitch = size; - initialData.SysMemSlicePitch = 0; - - result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer); - } - else - { - result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer); - } - - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY); - } - - mStagingBufferSize = size; - } - else if (data) - { - D3D11_MAPPED_SUBRESOURCE mappedResource; - result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource); - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY); - } - - memcpy(mappedResource.pData, data, size); - - context->Unmap(mStagingBuffer, 0); - } - } - - if (!mBuffer || mBufferSize < size + offset) - { - D3D11_BUFFER_DESC bufferDesc; - bufferDesc.ByteWidth = requiredBufferSize; - bufferDesc.Usage = D3D11_USAGE_DEFAULT; - if (mRenderer->getFeatureLevel() > D3D_FEATURE_LEVEL_9_3) - bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_INDEX_BUFFER; - else - bufferDesc.BindFlags = target == GL_ARRAY_BUFFER ? D3D11_BIND_VERTEX_BUFFER : D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = 0; - bufferDesc.MiscFlags = 0; - bufferDesc.StructureByteStride = 0; - - if (directInitialization) - { - // Since the data will fill the entire buffer (being larger than the initial size and having - // no offset), the buffer can be initialized with the data so no staging buffer is required - - // No longer need the old buffer - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - mBufferSize = 0; - } - - if (data) - { - D3D11_SUBRESOURCE_DATA initialData; - initialData.pSysMem = data; - initialData.SysMemPitch = size; - initialData.SysMemSlicePitch = 0; - - result = device->CreateBuffer(&bufferDesc, &initialData, &mBuffer); - } - else - { - result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer); - } - - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY); - } - } - else if (mBuffer && offset > 0) - { - // If offset is greater than zero and the buffer is non-null, need to preserve the data from - // the old buffer up to offset - ID3D11Buffer *newBuffer = NULL; - - result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer); - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY); - } - - D3D11_BOX srcBox; - srcBox.left = 0; - srcBox.right = std::min(offset, mBufferSize); - srcBox.top = 0; - srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; - - context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox); - - mBuffer->Release(); - mBuffer = newBuffer; - } - else - { - // Simple case, nothing needs to be copied from the old buffer to the new one, just create - // a new buffer - - // No longer need the old buffer - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - mBufferSize = 0; - } - - // Create a new buffer for data storage - result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer); - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY); - } - } - - updateSerial(); - mBufferSize = bufferDesc.ByteWidth; - } - - if (!directInitialization) - { - ASSERT(mStagingBuffer && mStagingBufferSize >= requiredStagingSize); - - // Data is already put into the staging buffer, copy it over to the data buffer - D3D11_BOX srcBox; - srcBox.left = 0; - srcBox.right = size; - srcBox.top = 0; - srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; - - context->CopySubresourceRegion(mBuffer, 0, offset, 0, 0, mStagingBuffer, 0, &srcBox); - } - - mSize = std::max(mSize, offset + size); - - mWriteUsageCount = 0; - - mResolvedDataValid = false; -} - -void BufferStorage11::clear() -{ - mResolvedDataValid = false; - mSize = 0; -} - -unsigned int BufferStorage11::getSize() const -{ - return mSize; -} - -bool BufferStorage11::supportsDirectBinding() const -{ - return mRenderer->getFeatureLevel() >= D3D_FEATURE_LEVEL_10_0; -} - -void BufferStorage11::markBufferUsage() -{ - mReadUsageCount++; - mWriteUsageCount++; - - static const unsigned int usageLimit = 5; - - if (mReadUsageCount > usageLimit && mResolvedData) - { - free(mResolvedData); - mResolvedData = NULL; - mResolvedDataSize = 0; - mResolvedDataValid = false; - } - - if (mReadUsageCount > usageLimit && mWriteUsageCount > usageLimit && mStagingBuffer) - { - mStagingBuffer->Release(); - mStagingBuffer = NULL; - mStagingBufferSize = 0; - } -} - -ID3D11Buffer *BufferStorage11::getBuffer() const -{ - return mBuffer; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.h deleted file mode 100644 index c9489627c3..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BufferStorage11.h Defines the BufferStorage11 class. - -#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ -#define LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ - -#include "libGLESv2/renderer/BufferStorage.h" - -namespace rx -{ -class Renderer11; - -class BufferStorage11 : public BufferStorage -{ - public: - explicit BufferStorage11(Renderer11 *renderer); - virtual ~BufferStorage11(); - - static BufferStorage11 *makeBufferStorage11(BufferStorage *bufferStorage); - - virtual void *getData(); - virtual void setData(const void* data, unsigned int size, unsigned int offset, unsigned int target); - virtual void clear(); - virtual unsigned int getSize() const; - virtual bool supportsDirectBinding() const; - virtual void markBufferUsage(); - - ID3D11Buffer *getBuffer() const; - - private: - Renderer11 *mRenderer; - - ID3D11Buffer *mStagingBuffer; - unsigned int mStagingBufferSize; - - ID3D11Buffer *mBuffer; - unsigned int mBufferSize; - - unsigned int mSize; - - void *mResolvedData; - unsigned int mResolvedDataSize; - bool mResolvedDataValid; - - unsigned int mReadUsageCount; - unsigned int mWriteUsageCount; -}; - -} - -#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp deleted file mode 100644 index 57fd29bf80..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BufferStorage9.cpp Defines the BufferStorage9 class. - -#include "libGLESv2/renderer/BufferStorage9.h" -#include "common/debug.h" - -namespace rx -{ - -BufferStorage9::BufferStorage9() -{ - mMemory = NULL; - mAllocatedSize = 0; - mSize = 0; -} - -BufferStorage9::~BufferStorage9() -{ - delete[] mMemory; -} - -BufferStorage9 *BufferStorage9::makeBufferStorage9(BufferStorage *bufferStorage) -{ - ASSERT(HAS_DYNAMIC_TYPE(BufferStorage9*, bufferStorage)); - return static_cast(bufferStorage); -} - -void *BufferStorage9::getData() -{ - return mMemory; -} - -void BufferStorage9::setData(const void* data, unsigned int size, unsigned int offset, unsigned int) -{ - if (!mMemory || offset + size > mAllocatedSize) - { - unsigned int newAllocatedSize = offset + size; - void *newMemory = new char[newAllocatedSize]; - - if (offset > 0 && mMemory && mAllocatedSize > 0) - { - memcpy(newMemory, mMemory, std::min(offset, mAllocatedSize)); - } - - delete[] mMemory; - mMemory = newMemory; - mAllocatedSize = newAllocatedSize; - } - - mSize = std::max(mSize, offset + size); - if (data) - { - memcpy(reinterpret_cast(mMemory) + offset, data, size); - } -} - -void BufferStorage9::clear() -{ - mSize = 0; -} - -unsigned int BufferStorage9::getSize() const -{ - return mSize; -} - -bool BufferStorage9::supportsDirectBinding() const -{ - return false; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.h deleted file mode 100644 index 82ae577e23..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BufferStorage9.h Defines the BufferStorage9 class. - -#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_ -#define LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_ - -#include "libGLESv2/renderer/BufferStorage.h" - -namespace rx -{ - -class BufferStorage9 : public BufferStorage -{ - public: - BufferStorage9(); - virtual ~BufferStorage9(); - - static BufferStorage9 *makeBufferStorage9(BufferStorage *bufferStorage); - - virtual void *getData(); - virtual void setData(const void* data, unsigned int size, unsigned int offset, unsigned int target = 0); - virtual void clear(); - virtual unsigned int getSize() const; - virtual bool supportsDirectBinding() const; - - private: - DISALLOW_COPY_AND_ASSIGN(BufferStorage9); - - void *mMemory; - unsigned int mAllocatedSize; - - unsigned int mSize; -}; - -} - -#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Fence11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Fence11.cpp deleted file mode 100644 index 9d11c9a0fc..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Fence11.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Fence11.cpp: Defines the rx::Fence11 class which implements rx::FenceImpl. - -#include "libGLESv2/renderer/Fence11.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/Renderer11.h" - -namespace rx -{ - -Fence11::Fence11(rx::Renderer11 *renderer) -{ - mRenderer = renderer; - mQuery = NULL; -} - -Fence11::~Fence11() -{ - if (mQuery) - { - mQuery->Release(); - mQuery = NULL; - } -} - -GLboolean Fence11::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 Fence11::setFence(GLenum condition) -{ - if (!mQuery) - { - D3D11_QUERY_DESC queryDesc; - queryDesc.Query = D3D11_QUERY_EVENT; - queryDesc.MiscFlags = 0; - - if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery))) - { - return gl::error(GL_OUT_OF_MEMORY); - } - } - - mRenderer->getDeviceContext()->End(mQuery); - - setCondition(condition); - setStatus(GL_FALSE); -} - -GLboolean Fence11::testFence() -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION, GL_TRUE); - } - - HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, 0); - - if (mRenderer->isDeviceLost()) - { - return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); - } - - ASSERT(result == S_OK || result == S_FALSE); - setStatus(result == S_OK); - return getStatus(); -} - -void Fence11::finishFence() -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - while (!testFence()) - { - Sleep(0); - } -} - -void Fence11::getFenceiv(GLenum pname, GLint *params) -{ - if (mQuery == NULL) - { - return gl::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 (getStatus()) - { - params[0] = GL_TRUE; - return; - } - - HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); - - if (mRenderer->isDeviceLost()) - { - params[0] = GL_TRUE; - return gl::error(GL_OUT_OF_MEMORY); - } - - ASSERT(result == S_OK || result == S_FALSE); - setStatus(result == S_OK); - params[0] = getStatus(); - - break; - } - case GL_FENCE_CONDITION_NV: - params[0] = getCondition(); - break; - default: - return gl::error(GL_INVALID_ENUM); - break; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Fence11.h b/src/3rdparty/angle/src/libGLESv2/renderer/Fence11.h deleted file mode 100644 index a5398bca14..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Fence11.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Fence11.h: Defines the rx::Fence11 class which implements rx::FenceImpl. - -#ifndef LIBGLESV2_RENDERER_Fence11_H_ -#define LIBGLESV2_RENDERER_Fence11_H_ - -#include "libGLESv2/renderer/FenceImpl.h" - -namespace rx -{ -class Renderer11; - -class Fence11 : public FenceImpl -{ - public: - explicit Fence11(rx::Renderer11 *renderer); - virtual ~Fence11(); - - GLboolean isFence(); - void setFence(GLenum condition); - GLboolean testFence(); - void finishFence(); - void getFenceiv(GLenum pname, GLint *params); - - private: - DISALLOW_COPY_AND_ASSIGN(Fence11); - - rx::Renderer11 *mRenderer; - ID3D11Query *mQuery; -}; - -} - -#endif // LIBGLESV2_RENDERER_FENCE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Fence9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Fence9.cpp deleted file mode 100644 index 86064d7e52..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Fence9.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Fence9.cpp: Defines the rx::Fence9 class. - -#include "libGLESv2/renderer/Fence9.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/renderer9_utils.h" -#include "libGLESv2/renderer/Renderer9.h" - -namespace rx -{ - -Fence9::Fence9(rx::Renderer9 *renderer) -{ - mRenderer = renderer; - mQuery = NULL; -} - -Fence9::~Fence9() -{ - if (mQuery) - { - mRenderer->freeEventQuery(mQuery); - mQuery = NULL; - } -} - -GLboolean Fence9::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 Fence9::setFence(GLenum condition) -{ - if (!mQuery) - { - mQuery = mRenderer->allocateEventQuery(); - if (!mQuery) - { - return gl::error(GL_OUT_OF_MEMORY); - } - } - - HRESULT result = mQuery->Issue(D3DISSUE_END); - ASSERT(SUCCEEDED(result)); - - setCondition(condition); - setStatus(GL_FALSE); -} - -GLboolean Fence9::testFence() -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION, GL_TRUE); - } - - HRESULT result = mQuery->GetData(NULL, 0, D3DGETDATA_FLUSH); - - if (d3d9::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); - } - - ASSERT(result == S_OK || result == S_FALSE); - setStatus(result == S_OK); - return getStatus(); -} - -void Fence9::finishFence() -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - while (!testFence()) - { - Sleep(0); - } -} - -void Fence9::getFenceiv(GLenum pname, GLint *params) -{ - if (mQuery == NULL) - { - return gl::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 (getStatus()) - { - params[0] = GL_TRUE; - return; - } - - HRESULT result = mQuery->GetData(NULL, 0, 0); - - if (d3d9::isDeviceLostError(result)) - { - params[0] = GL_TRUE; - mRenderer->notifyDeviceLost(); - return gl::error(GL_OUT_OF_MEMORY); - } - - ASSERT(result == S_OK || result == S_FALSE); - setStatus(result == S_OK); - params[0] = getStatus(); - - break; - } - case GL_FENCE_CONDITION_NV: - params[0] = getCondition(); - break; - default: - return gl::error(GL_INVALID_ENUM); - break; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Fence9.h b/src/3rdparty/angle/src/libGLESv2/renderer/Fence9.h deleted file mode 100644 index 9f17641e51..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Fence9.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Fence9.h: Defines the rx::Fence9 class which implements rx::FenceImpl. - -#ifndef LIBGLESV2_RENDERER_FENCE9_H_ -#define LIBGLESV2_RENDERER_FENCE9_H_ - -#include "libGLESv2/renderer/FenceImpl.h" - -namespace rx -{ -class Renderer9; - -class Fence9 : public FenceImpl -{ - public: - explicit Fence9(rx::Renderer9 *renderer); - virtual ~Fence9(); - - GLboolean isFence(); - void setFence(GLenum condition); - GLboolean testFence(); - void finishFence(); - void getFenceiv(GLenum pname, GLint *params); - - private: - DISALLOW_COPY_AND_ASSIGN(Fence9); - - rx::Renderer9 *mRenderer; - IDirect3DQuery9 *mQuery; -}; - -} - -#endif // LIBGLESV2_RENDERER_FENCE9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp deleted file mode 100644 index 81e9e9ecb2..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp +++ /dev/null @@ -1,460 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Image11.h: Implements the rx::Image11 class, which acts as the interface to -// the actual underlying resources of a Texture - -#include "libGLESv2/renderer/Renderer11.h" -#include "libGLESv2/renderer/Image11.h" -#include "libGLESv2/renderer/TextureStorage11.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" - -#include "libGLESv2/main.h" -#include "libGLESv2/utilities.h" -#include "libGLESv2/renderer/renderer11_utils.h" -#include "libGLESv2/renderer/generatemip.h" - -namespace rx -{ - -Image11::Image11() -{ - mStagingTexture = NULL; - mRenderer = NULL; - mDXGIFormat = DXGI_FORMAT_UNKNOWN; -} - -Image11::~Image11() -{ - if (mStagingTexture) - { - mStagingTexture->Release(); - } -} - -Image11 *Image11::makeImage11(Image *img) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::Image11*, img)); - return static_cast(img); -} - -void Image11::generateMipmap(Image11 *dest, Image11 *src) -{ - ASSERT(src->getDXGIFormat() == dest->getDXGIFormat()); - ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth()); - ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight()); - - D3D11_MAPPED_SUBRESOURCE destMapped, srcMapped; - dest->map(D3D11_MAP_WRITE, &destMapped); - src->map(D3D11_MAP_READ, &srcMapped); - - const unsigned char *sourceData = reinterpret_cast(srcMapped.pData); - unsigned char *destData = reinterpret_cast(destMapped.pData); - - if (sourceData && destData) - { - switch (src->getDXGIFormat()) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - case DXGI_FORMAT_B8G8R8A8_UNORM: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_A8_UNORM: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R8_UNORM: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R32G32B32A32_FLOAT: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R32G32B32_FLOAT: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R16G16B16A16_FLOAT: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R8G8_UNORM: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R16_FLOAT: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R16G16_FLOAT: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R32_FLOAT: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R32G32_FLOAT: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - default: - UNREACHABLE(); - break; - } - - dest->unmap(); - src->unmap(); - } - - dest->markDirty(); -} - -bool Image11::isDirty() const -{ - return (mStagingTexture && mDirty); -} - -bool Image11::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); - return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, width, height); -} - -bool Image11::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); - return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, face, xoffset, yoffset, width, height); -} - -bool Image11::redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) -{ - if (mWidth != width || - mHeight != height || - mInternalFormat != internalformat || - forceRelease) - { - mRenderer = Renderer11::makeRenderer11(renderer); - - mWidth = width; - mHeight = height; - mInternalFormat = internalformat; - // compute the d3d format that will be used - mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel()); - mActualFormat = d3d11_gl::ConvertTextureInternalFormat(mDXGIFormat); - - if (mStagingTexture) - { - mStagingTexture->Release(); - mStagingTexture = NULL; - } - - return true; - } - - return false; -} - -bool Image11::isRenderableFormat() const -{ - return TextureStorage11::IsTextureFormatRenderable(mDXGIFormat); -} - -DXGI_FORMAT Image11::getDXGIFormat() const -{ - // this should only happen if the image hasn't been redefined first - // which would be a bug by the caller - ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN); - - return mDXGIFormat; -} - -// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input -// into the target pixel rectangle. -void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input) -{ - D3D11_MAPPED_SUBRESOURCE mappedImage; - HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); - if (FAILED(result)) - { - ERR("Could not map image for loading."); - return; - } - - GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment); - size_t pixelSize = d3d11::ComputePixelSizeBits(mDXGIFormat) / 8; - void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + (yoffset * mappedImage.RowPitch + xoffset * pixelSize)); - - switch (mInternalFormat) - { - case GL_ALPHA8_EXT: - if (mRenderer->getFeatureLevel() >= D3D_FEATURE_LEVEL_10_0) - loadAlphaDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - else - loadAlphaDataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_LUMINANCE8_EXT: - loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false); - break; - case GL_ALPHA32F_EXT: - loadAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_LUMINANCE32F_EXT: - loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_ALPHA16F_EXT: - loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_LUMINANCE16F_EXT: - loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_LUMINANCE8_ALPHA8_EXT: - loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false); - break; - case GL_LUMINANCE_ALPHA32F_EXT: - loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_LUMINANCE_ALPHA16F_EXT: - loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGB8_OES: - loadRGBUByteDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGB565: - loadRGB565DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGBA8_OES: - loadRGBAUByteDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGBA4: - loadRGBA4444DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGB5_A1: - loadRGBA5551DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_BGRA8_EXT: - loadBGRADataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGB32F_EXT: - loadRGBFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGB16F_EXT: - loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGBA32F_EXT: - loadRGBAFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGBA16F_EXT: - loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - default: UNREACHABLE(); - } - - unmap(); -} - -void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - const void *input) -{ - ASSERT(xoffset % 4 == 0); - ASSERT(yoffset % 4 == 0); - - D3D11_MAPPED_SUBRESOURCE mappedImage; - HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); - if (FAILED(result)) - { - ERR("Could not map image for loading."); - return; - } - - // Size computation assumes a 4x4 block compressed texture format - size_t blockSize = d3d11::ComputeBlockSizeBits(mDXGIFormat) / 8; - void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + ((yoffset / 4) * mappedImage.RowPitch + (xoffset / 4) * blockSize)); - - GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat); - GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat); - int rows = inputSize / inputPitch; - for (int i = 0; i < rows; ++i) - { - memcpy((void*)((BYTE*)offsetMappedData + i * mappedImage.RowPitch), (void*)((BYTE*)input + i * inputPitch), inputPitch); - } - - unmap(); -} - -void Image11::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) -{ - gl::Renderbuffer *colorbuffer = source->getReadColorbuffer(); - - if (colorbuffer && colorbuffer->getActualFormat() == (GLuint)mActualFormat) - { - // No conversion needed-- use copyback fastpath - ID3D11Texture2D *colorBufferTexture = NULL; - unsigned int subresourceIndex = 0; - - if (mRenderer->getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) - { - D3D11_TEXTURE2D_DESC textureDesc; - colorBufferTexture->GetDesc(&textureDesc); - - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - ID3D11Texture2D* srcTex = NULL; - if (textureDesc.SampleDesc.Count > 1) - { - D3D11_TEXTURE2D_DESC resolveDesc; - resolveDesc.Width = textureDesc.Width; - resolveDesc.Height = textureDesc.Height; - resolveDesc.MipLevels = 1; - resolveDesc.ArraySize = 1; - resolveDesc.Format = textureDesc.Format; - resolveDesc.SampleDesc.Count = 1; - resolveDesc.SampleDesc.Quality = 0; - resolveDesc.Usage = D3D11_USAGE_DEFAULT; - resolveDesc.BindFlags = 0; - resolveDesc.CPUAccessFlags = 0; - resolveDesc.MiscFlags = 0; - - HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex); - if (FAILED(result)) - { - ERR("Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result); - return; - } - - deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format); - subresourceIndex = 0; - } - else - { - srcTex = colorBufferTexture; - srcTex->AddRef(); - } - - D3D11_BOX srcBox; - srcBox.left = x; - srcBox.right = x + width; - srcBox.top = y; - srcBox.bottom = y + height; - srcBox.front = 0; - srcBox.back = 1; - - deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, 0, srcTex, subresourceIndex, &srcBox); - - srcTex->Release(); - colorBufferTexture->Release(); - } - } - else - { - // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels - D3D11_MAPPED_SUBRESOURCE mappedImage; - HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); - - // determine the offset coordinate into the destination buffer - GLsizei rowOffset = gl::ComputePixelSize(mActualFormat) * xoffset; - void *dataOffset = static_cast(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset; - - mRenderer->readPixels(source, x, y, width, height, gl::ExtractFormat(mInternalFormat), - gl::ExtractType(mInternalFormat), mappedImage.RowPitch, false, 4, dataOffset); - - unmap(); - } -} - -ID3D11Texture2D *Image11::getStagingTexture() -{ - createStagingTexture(); - - return mStagingTexture; -} - -unsigned int Image11::getStagingSubresource() -{ - createStagingTexture(); - - return mStagingSubresource; -} - -void Image11::createStagingTexture() -{ - if (mStagingTexture) - { - return; - } - - ID3D11Texture2D *newTexture = NULL; - int lodOffset = 1; - const DXGI_FORMAT dxgiFormat = getDXGIFormat(); - ASSERT(!d3d11::IsDepthStencilFormat(dxgiFormat)); // We should never get here for depth textures - - if (mWidth != 0 && mHeight != 0) - { - GLsizei width = mWidth; - GLsizei height = mHeight; - - // adjust size if needed for compressed textures - gl::MakeValidSize(false, d3d11::IsCompressed(dxgiFormat), &width, &height, &lodOffset); - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE2D_DESC desc; - desc.Width = width; - desc.Height = height; - desc.MipLevels = lodOffset + 1; - desc.ArraySize = 1; - desc.Format = dxgiFormat; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_STAGING; - desc.BindFlags = 0; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; - - HRESULT result = device->CreateTexture2D(&desc, NULL, &newTexture); - - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - ERR("Creating image failed."); - return gl::error(GL_OUT_OF_MEMORY); - } - } - - mStagingTexture = newTexture; - mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); - mDirty = false; -} - -HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) -{ - createStagingTexture(); - - HRESULT result = E_FAIL; - - if (mStagingTexture) - { - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - result = deviceContext->Map(mStagingTexture, mStagingSubresource, mapType, 0, map); - - // this can fail if the device is removed (from TDR) - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - } - else if (SUCCEEDED(result)) - { - mDirty = true; - } - } - - return result; -} - -void Image11::unmap() -{ - if (mStagingTexture) - { - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - deviceContext->Unmap(mStagingTexture, mStagingSubresource); - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.h b/src/3rdparty/angle/src/libGLESv2/renderer/Image11.h deleted file mode 100644 index 11a6492dc8..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.h +++ /dev/null @@ -1,76 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Image11.h: Defines the rx::Image11 class, which acts as the interface to -// the actual underlying resources of a Texture - -#ifndef LIBGLESV2_RENDERER_IMAGE11_H_ -#define LIBGLESV2_RENDERER_IMAGE11_H_ - -#include "libGLESv2/renderer/Image.h" - -#include "common/debug.h" - -namespace gl -{ -class Framebuffer; -} - -namespace rx -{ -class Renderer; -class Renderer11; -class TextureStorageInterface2D; -class TextureStorageInterfaceCube; - -class Image11 : public Image -{ - public: - Image11(); - virtual ~Image11(); - - static Image11 *makeImage11(Image *img); - - static void generateMipmap(Image11 *dest, Image11 *src); - - virtual bool isDirty() const; - - virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - - virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease); - - virtual bool isRenderableFormat() const; - DXGI_FORMAT getDXGIFormat() const; - - virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input); - virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - const void *input); - - virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - - protected: - HRESULT map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map); - void unmap(); - - private: - DISALLOW_COPY_AND_ASSIGN(Image11); - - ID3D11Texture2D *getStagingTexture(); - unsigned int getStagingSubresource(); - void createStagingTexture(); - - Renderer11 *mRenderer; - - DXGI_FORMAT mDXGIFormat; - ID3D11Texture2D *mStagingTexture; - unsigned int mStagingSubresource; -}; - -} - -#endif // LIBGLESV2_RENDERER_IMAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Image9.cpp deleted file mode 100644 index 53030b7f1e..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image9.cpp +++ /dev/null @@ -1,736 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Image9.cpp: Implements the rx::Image9 class, which acts as the interface to -// the actual underlying surfaces of a Texture. - -#include "libGLESv2/renderer/Image9.h" - -#include "libGLESv2/main.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/renderer/Renderer9.h" -#include "libGLESv2/renderer/RenderTarget9.h" -#include "libGLESv2/renderer/TextureStorage9.h" - -#include "libGLESv2/renderer/renderer9_utils.h" -#include "libGLESv2/renderer/generatemip.h" - -namespace rx -{ - -Image9::Image9() -{ - mSurface = NULL; - mRenderer = NULL; - - mD3DPool = D3DPOOL_SYSTEMMEM; - mD3DFormat = D3DFMT_UNKNOWN; -} - -Image9::~Image9() -{ - if (mSurface) - { - mSurface->Release(); - } -} - -void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface) -{ - D3DSURFACE_DESC destDesc; - HRESULT result = destSurface->GetDesc(&destDesc); - ASSERT(SUCCEEDED(result)); - - D3DSURFACE_DESC sourceDesc; - result = sourceSurface->GetDesc(&sourceDesc); - ASSERT(SUCCEEDED(result)); - - ASSERT(sourceDesc.Format == destDesc.Format); - ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width); - ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height); - - D3DLOCKED_RECT sourceLocked = {0}; - result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY); - ASSERT(SUCCEEDED(result)); - - D3DLOCKED_RECT destLocked = {0}; - result = destSurface->LockRect(&destLocked, NULL, 0); - ASSERT(SUCCEEDED(result)); - - const unsigned char *sourceData = reinterpret_cast(sourceLocked.pBits); - unsigned char *destData = reinterpret_cast(destLocked.pBits); - - if (sourceData && destData) - { - switch (sourceDesc.Format) - { - case D3DFMT_L8: - GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - case D3DFMT_A8L8: - GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: - GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - case D3DFMT_A16B16G16R16F: - GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - case D3DFMT_A32B32G32R32F: - GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - default: - UNREACHABLE(); - break; - } - - destSurface->UnlockRect(); - sourceSurface->UnlockRect(); - } -} - -Image9 *Image9::makeImage9(Image *img) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::Image9*, img)); - return static_cast(img); -} - -void Image9::generateMipmap(Image9 *dest, Image9 *source) -{ - IDirect3DSurface9 *sourceSurface = source->getSurface(); - if (sourceSurface == NULL) - return gl::error(GL_OUT_OF_MEMORY); - - IDirect3DSurface9 *destSurface = dest->getSurface(); - generateMip(destSurface, sourceSurface); - - dest->markDirty(); -} - -void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source) -{ - D3DLOCKED_RECT sourceLock = {0}; - D3DLOCKED_RECT destLock = {0}; - - source->LockRect(&sourceLock, NULL, 0); - dest->LockRect(&destLock, NULL, 0); - - if (sourceLock.pBits && destLock.pBits) - { - D3DSURFACE_DESC desc; - source->GetDesc(&desc); - - int rows = d3d9::IsCompressedFormat(desc.Format) ? desc.Height / 4 : desc.Height; - int bytes = d3d9::ComputeRowSize(desc.Format, desc.Width); - ASSERT(bytes <= sourceLock.Pitch && bytes <= destLock.Pitch); - - for(int i = 0; i < rows; i++) - { - memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes); - } - - source->UnlockRect(); - dest->UnlockRect(); - } - else UNREACHABLE(); -} - -bool Image9::redefine(rx::Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) -{ - if (mWidth != width || - mHeight != height || - mInternalFormat != internalformat || - forceRelease) - { - mRenderer = Renderer9::makeRenderer9(renderer); - - mWidth = width; - mHeight = height; - mInternalFormat = internalformat; - // compute the d3d format that will be used - mD3DFormat = mRenderer->ConvertTextureInternalFormat(internalformat); - mActualFormat = d3d9_gl::GetEquivalentFormat(mD3DFormat); - - if (mSurface) - { - mSurface->Release(); - mSurface = NULL; - } - - return true; - } - - return false; -} - -void Image9::createSurface() -{ - if(mSurface) - { - return; - } - - IDirect3DTexture9 *newTexture = NULL; - IDirect3DSurface9 *newSurface = NULL; - const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM; - const D3DFORMAT d3dFormat = getD3DFormat(); - ASSERT(d3dFormat != D3DFMT_INTZ); // We should never get here for depth textures - - if (mWidth != 0 && mHeight != 0) - { - int levelToFetch = 0; - GLsizei requestWidth = mWidth; - GLsizei requestHeight = mHeight; - gl::MakeValidSize(true, gl::IsCompressed(mInternalFormat), &requestWidth, &requestHeight, &levelToFetch); - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0, d3dFormat, - poolToUse, &newTexture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - ERR("Creating image surface failed."); - return gl::error(GL_OUT_OF_MEMORY); - } - - newTexture->GetSurfaceLevel(levelToFetch, &newSurface); - newTexture->Release(); - } - - mSurface = newSurface; - mDirty = false; - mD3DPool = poolToUse; -} - -HRESULT Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect) -{ - createSurface(); - - HRESULT result = D3DERR_INVALIDCALL; - - if (mSurface) - { - result = mSurface->LockRect(lockedRect, rect, 0); - ASSERT(SUCCEEDED(result)); - - mDirty = true; - } - - return result; -} - -void Image9::unlock() -{ - if (mSurface) - { - HRESULT result = mSurface->UnlockRect(); - ASSERT(SUCCEEDED(result)); - } -} - -bool Image9::isRenderableFormat() const -{ - return TextureStorage9::IsTextureFormatRenderable(getD3DFormat()); -} - -D3DFORMAT Image9::getD3DFormat() const -{ - // this should only happen if the image hasn't been redefined first - // which would be a bug by the caller - ASSERT(mD3DFormat != D3DFMT_UNKNOWN); - - return mD3DFormat; -} - -IDirect3DSurface9 *Image9::getSurface() -{ - createSurface(); - - return mSurface; -} - -void Image9::setManagedSurface(TextureStorageInterface2D *storage, int level) -{ - TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); - setManagedSurface(storage9->getSurfaceLevel(level, false)); -} - -void Image9::setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level) -{ - TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); - setManagedSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false)); -} - -void Image9::setManagedSurface(IDirect3DSurface9 *surface) -{ - D3DSURFACE_DESC desc; - surface->GetDesc(&desc); - ASSERT(desc.Pool == D3DPOOL_MANAGED); - - if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight) - { - if (mSurface) - { - copyLockableSurfaces(surface, mSurface); - mSurface->Release(); - } - - mSurface = surface; - mD3DPool = desc.Pool; - } -} - -bool Image9::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - ASSERT(getSurface() != NULL); - TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); - return updateSurface(storage9->getSurfaceLevel(level, true), xoffset, yoffset, width, height); -} - -bool Image9::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - ASSERT(getSurface() != NULL); - TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); - return updateSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true), xoffset, yoffset, width, height); -} - -bool Image9::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - if (!destSurface) - return false; - - IDirect3DSurface9 *sourceSurface = getSurface(); - - if (sourceSurface && sourceSurface != destSurface) - { - RECT rect; - rect.left = xoffset; - rect.top = yoffset; - rect.right = xoffset + width; - rect.bottom = yoffset + height; - - POINT point = {rect.left, rect.top}; - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - if (mD3DPool == D3DPOOL_MANAGED) - { - D3DSURFACE_DESC desc; - sourceSurface->GetDesc(&desc); - - IDirect3DSurface9 *surf = 0; - HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); - - if (SUCCEEDED(result)) - { - copyLockableSurfaces(surf, sourceSurface); - result = device->UpdateSurface(surf, &rect, destSurface, &point); - ASSERT(SUCCEEDED(result)); - surf->Release(); - } - } - else - { - // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools - HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point); - ASSERT(SUCCEEDED(result)); - } - } - - destSurface->Release(); - return true; -} - -// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input -// into the target pixel rectangle. -void Image9::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input) -{ - RECT lockRect = - { - xoffset, yoffset, - xoffset + width, yoffset + height - }; - - D3DLOCKED_RECT locked; - HRESULT result = lock(&locked, &lockRect); - if (FAILED(result)) - { - return; - } - - - GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment); - - switch (mInternalFormat) - { - case GL_ALPHA8_EXT: -#if defined(__SSE2__) - if (gl::supportsSSE2()) - { - loadAlphaDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - else -#endif - { - loadAlphaDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - break; - case GL_LUMINANCE8_EXT: - loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_L8); - break; - case GL_ALPHA32F_EXT: - loadAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE32F_EXT: - loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_ALPHA16F_EXT: - loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE16F_EXT: - loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE8_ALPHA8_EXT: - loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_A8L8); - break; - case GL_LUMINANCE_ALPHA32F_EXT: - loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE_ALPHA16F_EXT: - loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB8_OES: - loadRGBUByteDataToBGRX(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB565: - loadRGB565DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGBA8_OES: -#if defined(__SSE2__) - if (gl::supportsSSE2()) - { - loadRGBAUByteDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - else -#endif - { - loadRGBAUByteDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - break; - case GL_RGBA4: - loadRGBA4444DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB5_A1: - loadRGBA5551DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_BGRA8_EXT: - loadBGRADataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D - case GL_RGB32F_EXT: - loadRGBFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB16F_EXT: - loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGBA32F_EXT: - loadRGBAFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGBA16F_EXT: - loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - default: UNREACHABLE(); - } - - unlock(); -} - -void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - const void *input) -{ - ASSERT(xoffset % 4 == 0); - ASSERT(yoffset % 4 == 0); - - RECT lockRect = { - xoffset, yoffset, - xoffset + width, yoffset + height - }; - - D3DLOCKED_RECT locked; - HRESULT result = lock(&locked, &lockRect); - if (FAILED(result)) - { - return; - } - - GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat); - GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat); - int rows = inputSize / inputPitch; - for (int i = 0; i < rows; ++i) - { - memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)input + i * inputPitch), inputPitch); - } - - unlock(); -} - -// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures -void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) -{ - RenderTarget9 *renderTarget = NULL; - IDirect3DSurface9 *surface = NULL; - gl::Renderbuffer *colorbuffer = source->getColorbuffer(0); - - if (colorbuffer) - { - renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); - } - - if (renderTarget) - { - surface = renderTarget->getSurface(); - } - - if (!surface) - { - ERR("Failed to retrieve the render target."); - return gl::error(GL_OUT_OF_MEMORY); - } - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - IDirect3DSurface9 *renderTargetData = NULL; - D3DSURFACE_DESC description; - surface->GetDesc(&description); - - HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL); - - if (FAILED(result)) - { - ERR("Could not create matching destination surface."); - surface->Release(); - return gl::error(GL_OUT_OF_MEMORY); - } - - result = device->GetRenderTargetData(surface, renderTargetData); - - if (FAILED(result)) - { - ERR("GetRenderTargetData unexpectedly failed."); - renderTargetData->Release(); - surface->Release(); - return gl::error(GL_OUT_OF_MEMORY); - } - - RECT sourceRect = {x, y, x + width, y + height}; - RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height}; - - D3DLOCKED_RECT sourceLock = {0}; - result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0); - - if (FAILED(result)) - { - ERR("Failed to lock the source surface (rectangle might be invalid)."); - renderTargetData->Release(); - surface->Release(); - return gl::error(GL_OUT_OF_MEMORY); - } - - D3DLOCKED_RECT destLock = {0}; - result = lock(&destLock, &destRect); - - if (FAILED(result)) - { - ERR("Failed to lock the destination surface (rectangle might be invalid)."); - renderTargetData->UnlockRect(); - renderTargetData->Release(); - surface->Release(); - return gl::error(GL_OUT_OF_MEMORY); - } - - if (destLock.pBits && sourceLock.pBits) - { - unsigned char *source = (unsigned char*)sourceLock.pBits; - unsigned char *dest = (unsigned char*)destLock.pBits; - - switch (description.Format) - { - case D3DFMT_X8R8G8B8: - case D3DFMT_A8R8G8B8: - switch(getD3DFormat()) - { - case D3DFMT_X8R8G8B8: - case D3DFMT_A8R8G8B8: - for(int y = 0; y < height; y++) - { - memcpy(dest, source, 4 * width); - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - dest[x] = source[x * 4 + 2]; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_A8L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - dest[x * 2 + 0] = source[x * 4 + 2]; - dest[x * 2 + 1] = source[x * 4 + 3]; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - default: - UNREACHABLE(); - } - break; - case D3DFMT_R5G6B5: - switch(getD3DFormat()) - { - case D3DFMT_X8R8G8B8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned short rgb = ((unsigned short*)source)[x]; - unsigned char red = (rgb & 0xF800) >> 8; - unsigned char green = (rgb & 0x07E0) >> 3; - unsigned char blue = (rgb & 0x001F) << 3; - dest[x + 0] = blue | (blue >> 5); - dest[x + 1] = green | (green >> 6); - dest[x + 2] = red | (red >> 5); - dest[x + 3] = 0xFF; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned char red = source[x * 2 + 1] & 0xF8; - dest[x] = red | (red >> 5); - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - default: - UNREACHABLE(); - } - break; - case D3DFMT_A1R5G5B5: - switch(getD3DFormat()) - { - case D3DFMT_X8R8G8B8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned short argb = ((unsigned short*)source)[x]; - unsigned char red = (argb & 0x7C00) >> 7; - unsigned char green = (argb & 0x03E0) >> 2; - unsigned char blue = (argb & 0x001F) << 3; - dest[x + 0] = blue | (blue >> 5); - dest[x + 1] = green | (green >> 5); - dest[x + 2] = red | (red >> 5); - dest[x + 3] = 0xFF; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_A8R8G8B8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned short argb = ((unsigned short*)source)[x]; - unsigned char red = (argb & 0x7C00) >> 7; - unsigned char green = (argb & 0x03E0) >> 2; - unsigned char blue = (argb & 0x001F) << 3; - unsigned char alpha = (signed short)argb >> 15; - dest[x + 0] = blue | (blue >> 5); - dest[x + 1] = green | (green >> 5); - dest[x + 2] = red | (red >> 5); - dest[x + 3] = alpha; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned char red = source[x * 2 + 1] & 0x7C; - dest[x] = (red << 1) | (red >> 4); - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_A8L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned char red = source[x * 2 + 1] & 0x7C; - dest[x * 2 + 0] = (red << 1) | (red >> 4); - dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - default: - UNREACHABLE(); - } - break; - default: - UNREACHABLE(); - } - } - - unlock(); - renderTargetData->UnlockRect(); - - renderTargetData->Release(); - surface->Release(); - - mDirty = true; -} - -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image9.h b/src/3rdparty/angle/src/libGLESv2/renderer/Image9.h deleted file mode 100644 index 2fbbca3124..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image9.h +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Image9.h: Defines the rx::Image9 class, which acts as the interface to -// the actual underlying surfaces of a Texture. - -#ifndef LIBGLESV2_RENDERER_IMAGE9_H_ -#define LIBGLESV2_RENDERER_IMAGE9_H_ - -#include "libGLESv2/renderer/Image.h" -#include "common/debug.h" - -namespace gl -{ -class Framebuffer; -} - -namespace rx -{ -class Renderer; -class Renderer9; -class TextureStorageInterface2D; -class TextureStorageInterfaceCube; - -class Image9 : public Image -{ - public: - Image9(); - ~Image9(); - - static Image9 *makeImage9(Image *img); - - static void generateMipmap(Image9 *dest, Image9 *source); - static void generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface); - static void copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source); - - virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease); - - virtual bool isRenderableFormat() const; - D3DFORMAT getD3DFormat() const; - - virtual bool isDirty() const {return mSurface && mDirty;} - IDirect3DSurface9 *getSurface(); - - virtual void setManagedSurface(TextureStorageInterface2D *storage, int level); - virtual void setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level); - virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - - virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input); - virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - const void *input); - - virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - - private: - DISALLOW_COPY_AND_ASSIGN(Image9); - - void createSurface(); - void setManagedSurface(IDirect3DSurface9 *surface); - bool updateSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - - HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect); - void unlock(); - - Renderer9 *mRenderer; - - D3DPOOL mD3DPool; // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable. - D3DFORMAT mD3DFormat; - - IDirect3DSurface9 *mSurface; -}; -} - -#endif // LIBGLESV2_RENDERER_IMAGE9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp deleted file mode 100644 index 36a62adc1c..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp +++ /dev/null @@ -1,183 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation. - -#include "libGLESv2/renderer/IndexBuffer11.h" -#include "libGLESv2/renderer/Renderer11.h" - -namespace rx -{ - -IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) -{ - mBuffer = NULL; - mBufferSize = 0; - mDynamicUsage = false; -} - -IndexBuffer11::~IndexBuffer11() -{ - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - } -} - -bool IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) -{ - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - } - - updateSerial(); - - if (bufferSize > 0) - { - ID3D11Device* dxDevice = mRenderer->getDevice(); - - D3D11_BUFFER_DESC bufferDesc; - bufferDesc.ByteWidth = bufferSize; - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - bufferDesc.MiscFlags = 0; - bufferDesc.StructureByteStride = 0; - - HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); - if (FAILED(result)) - { - return false; - } - } - - mBufferSize = bufferSize; - mIndexType = indexType; - mDynamicUsage = dynamic; - - return true; -} - -IndexBuffer11 *IndexBuffer11::makeIndexBuffer11(IndexBuffer *indexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer11*, indexBuffer)); - return static_cast(indexBuffer); -} - -bool IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) -{ - if (mBuffer) - { - // Check for integer overflows and out-out-bounds map requests - if (offset + size < offset || offset + size > mBufferSize) - { - ERR("Index buffer map range is not inside the buffer."); - return false; - } - - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Index buffer map failed with error 0x%08x", result); - return false; - } - - *outMappedMemory = reinterpret_cast(mappedResource.pData) + offset; - return true; - } - else - { - ERR("Index buffer not initialized."); - return false; - } -} - -bool IndexBuffer11::unmapBuffer() -{ - if (mBuffer) - { - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - dxContext->Unmap(mBuffer, 0); - return true; - } - else - { - ERR("Index buffer not initialized."); - return false; - } -} - -GLenum IndexBuffer11::getIndexType() const -{ - return mIndexType; -} - -unsigned int IndexBuffer11::getBufferSize() const -{ - return mBufferSize; -} - -bool IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType) -{ - if (bufferSize > mBufferSize || indexType != mIndexType) - { - return initialize(bufferSize, indexType, mDynamicUsage); - } - else - { - return true; - } -} - -bool IndexBuffer11::discard() -{ - if (mBuffer) - { - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Index buffer map failed with error 0x%08x", result); - return false; - } - - dxContext->Unmap(mBuffer, 0); - - return true; - } - else - { - ERR("Index buffer not initialized."); - return false; - } -} - -DXGI_FORMAT IndexBuffer11::getIndexFormat() const -{ - switch (mIndexType) - { - case GL_UNSIGNED_BYTE: return DXGI_FORMAT_R16_UINT; - case GL_UNSIGNED_SHORT: return DXGI_FORMAT_R16_UINT; - case GL_UNSIGNED_INT: return mRenderer->get32BitIndexSupport() ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT; - default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; - } -} - -ID3D11Buffer *IndexBuffer11::getBuffer() const -{ - return mBuffer; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.h deleted file mode 100644 index 39a61946ad..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// IndexBuffer11.h: Defines the D3D11 IndexBuffer implementation. - -#ifndef LIBGLESV2_RENDERER_INDEXBUFFER11_H_ -#define LIBGLESV2_RENDERER_INDEXBUFFER11_H_ - -#include "libGLESv2/renderer/IndexBuffer.h" - -namespace rx -{ -class Renderer11; - -class IndexBuffer11 : public IndexBuffer -{ - public: - explicit IndexBuffer11(Renderer11 *const renderer); - virtual ~IndexBuffer11(); - - virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); - - static IndexBuffer11 *makeIndexBuffer11(IndexBuffer *indexBuffer); - - virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); - virtual bool unmapBuffer(); - - virtual GLenum getIndexType() const; - virtual unsigned int getBufferSize() const; - virtual bool setSize(unsigned int bufferSize, GLenum indexType); - - virtual bool discard(); - - DXGI_FORMAT getIndexFormat() const; - ID3D11Buffer *getBuffer() const; - - private: - DISALLOW_COPY_AND_ASSIGN(IndexBuffer11); - - rx::Renderer11 *const mRenderer; - - ID3D11Buffer *mBuffer; - unsigned int mBufferSize; - GLenum mIndexType; - bool mDynamicUsage; -}; - -} - -#endif // LIBGLESV2_RENDERER_INDEXBUFFER11_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer9.cpp deleted file mode 100644 index c6d83c5dca..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer9.cpp +++ /dev/null @@ -1,207 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation. - -#include "libGLESv2/renderer/IndexBuffer9.h" -#include "libGLESv2/renderer/Renderer9.h" - -namespace rx -{ - -IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer) -{ - mIndexBuffer = NULL; - mBufferSize = 0; - mIndexType = 0; - mDynamic = false; -} - -IndexBuffer9::~IndexBuffer9() -{ - if (mIndexBuffer) - { - mIndexBuffer->Release(); - mIndexBuffer = NULL; - } -} - -bool IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) -{ - if (mIndexBuffer) - { - mIndexBuffer->Release(); - mIndexBuffer = NULL; - } - - updateSerial(); - - if (bufferSize > 0) - { - D3DFORMAT format; - if (indexType == GL_UNSIGNED_SHORT || indexType == GL_UNSIGNED_BYTE) - { - format = D3DFMT_INDEX16; - } - else if (indexType == GL_UNSIGNED_INT) - { - if (mRenderer->get32BitIndexSupport()) - { - format = D3DFMT_INDEX32; - } - else - { - ERR("Attempted to create a 32-bit index buffer but renderer does not support 32-bit indices."); - return false; - } - } - else - { - ERR("Invalid index type %u.", indexType); - return false; - } - - DWORD usageFlags = D3DUSAGE_WRITEONLY; - if (dynamic) - { - usageFlags |= D3DUSAGE_DYNAMIC; - } - - HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer); - if (FAILED(result)) - { - ERR("Failed to create an index buffer of size %u, result: 0x%08x.", mBufferSize, result); - return false; - } - } - - mBufferSize = bufferSize; - mIndexType = indexType; - mDynamic = dynamic; - - return true; -} - -IndexBuffer9 *IndexBuffer9::makeIndexBuffer9(IndexBuffer *indexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer9*, indexBuffer)); - return static_cast(indexBuffer); -} - -bool IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) -{ - if (mIndexBuffer) - { - DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0; - - void *mapPtr = NULL; - HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags); - if (FAILED(result)) - { - ERR("Index buffer lock failed with error 0x%08x", result); - return false; - } - - *outMappedMemory = mapPtr; - return true; - } - else - { - ERR("Index buffer not initialized."); - return false; - } -} - -bool IndexBuffer9::unmapBuffer() -{ - if (mIndexBuffer) - { - HRESULT result = mIndexBuffer->Unlock(); - if (FAILED(result)) - { - ERR("Index buffer unlock failed with error 0x%08x", result); - return false; - } - - return true; - } - else - { - ERR("Index buffer not initialized."); - return false; - } -} - -GLenum IndexBuffer9::getIndexType() const -{ - return mIndexType; -} - -unsigned int IndexBuffer9::getBufferSize() const -{ - return mBufferSize; -} - -bool IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType) -{ - if (bufferSize > mBufferSize || indexType != mIndexType) - { - return initialize(bufferSize, indexType, mDynamic); - } - else - { - return true; - } -} - -bool IndexBuffer9::discard() -{ - if (mIndexBuffer) - { - void *dummy; - HRESULT result; - - result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); - if (FAILED(result)) - { - ERR("Discard lock failed with error 0x%08x", result); - return false; - } - - result = mIndexBuffer->Unlock(); - if (FAILED(result)) - { - ERR("Discard unlock failed with error 0x%08x", result); - return false; - } - - return true; - } - else - { - ERR("Index buffer not initialized."); - return false; - } -} - -D3DFORMAT IndexBuffer9::getIndexFormat() const -{ - switch (mIndexType) - { - case GL_UNSIGNED_BYTE: return D3DFMT_INDEX16; - case GL_UNSIGNED_SHORT: return D3DFMT_INDEX16; - case GL_UNSIGNED_INT: return D3DFMT_INDEX32; - default: UNREACHABLE(); return D3DFMT_UNKNOWN; - } -} - -IDirect3DIndexBuffer9 * IndexBuffer9::getBuffer() const -{ - return mIndexBuffer; -} - -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer9.h deleted file mode 100644 index 6801867532..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer9.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Indexffer9.h: Defines the D3D9 IndexBuffer implementation. - -#ifndef LIBGLESV2_RENDERER_INDEXBUFFER9_H_ -#define LIBGLESV2_RENDERER_INDEXBUFFER9_H_ - -#include "libGLESv2/renderer/IndexBuffer.h" - -namespace rx -{ -class Renderer9; - -class IndexBuffer9 : public IndexBuffer -{ - public: - explicit IndexBuffer9(Renderer9 *const renderer); - virtual ~IndexBuffer9(); - - virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); - - static IndexBuffer9 *makeIndexBuffer9(IndexBuffer *indexBuffer); - - virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); - virtual bool unmapBuffer(); - - virtual GLenum getIndexType() const; - virtual unsigned int getBufferSize() const; - virtual bool setSize(unsigned int bufferSize, GLenum indexType); - - virtual bool discard(); - - D3DFORMAT getIndexFormat() const; - IDirect3DIndexBuffer9 *getBuffer() const; - - private: - DISALLOW_COPY_AND_ASSIGN(IndexBuffer9); - - rx::Renderer9 *const mRenderer; - - IDirect3DIndexBuffer9 *mIndexBuffer; - unsigned int mBufferSize; - GLenum mIndexType; - bool mDynamic; -}; - -} - -#endif // LIBGLESV2_RENDERER_INDEXBUFFER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp deleted file mode 100644 index 1552f3a326..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp +++ /dev/null @@ -1,213 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches -// D3D11 input layouts. - -#include "libGLESv2/renderer/InputLayoutCache.h" -#include "libGLESv2/renderer/VertexBuffer11.h" -#include "libGLESv2/renderer/BufferStorage11.h" -#include "libGLESv2/renderer/ShaderExecutable11.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/renderer/VertexDataManager.h" - -#include "third_party/murmurhash/MurmurHash3.h" - -namespace rx -{ - -const unsigned int InputLayoutCache::kMaxInputLayouts = 1024; - -InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts) -{ - mCounter = 0; - mDevice = NULL; - mDeviceContext = NULL; - mCurrentIL = NULL; - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mCurrentBuffers[i] = -1; - mCurrentVertexStrides[i] = -1; - mCurrentVertexOffsets[i] = -1; - } -} - -InputLayoutCache::~InputLayoutCache() -{ - clear(); -} - -void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context) -{ - clear(); - mDevice = device; - mDeviceContext = context; -} - -void InputLayoutCache::clear() -{ - for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) - { - i->second.inputLayout->Release(); - } - mInputLayoutMap.clear(); - markDirty(); -} - -void InputLayoutCache::markDirty() -{ - mCurrentIL = NULL; - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mCurrentBuffers[i] = -1; - mCurrentVertexStrides[i] = -1; - mCurrentVertexOffsets[i] = -1; - } -} - -GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], - gl::ProgramBinary *programBinary) -{ - int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]; - programBinary->sortAttributesByLayout(attributes, sortedSemanticIndices); - - if (!mDevice || !mDeviceContext) - { - ERR("InputLayoutCache is not initialized."); - return GL_INVALID_OPERATION; - } - - InputLayoutKey ilKey = { 0 }; - - ID3D11Buffer *vertexBuffers[gl::MAX_VERTEX_ATTRIBS] = { NULL }; - unsigned int vertexBufferSerials[gl::MAX_VERTEX_ATTRIBS] = { 0 }; - UINT vertexStrides[gl::MAX_VERTEX_ATTRIBS] = { 0 }; - UINT vertexOffsets[gl::MAX_VERTEX_ATTRIBS] = { 0 }; - - static const char* semanticName = "TEXCOORD"; - - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - if (attributes[i].active) - { - VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer); - BufferStorage11 *bufferStorage = attributes[i].storage ? BufferStorage11::makeBufferStorage11(attributes[i].storage) : NULL; - - D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; - - // Record the type of the associated vertex shader vector in our key - // This will prevent mismatched vertex shaders from using the same input layout - GLint attributeSize; - programBinary->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL); - - ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName; - ilKey.elements[ilKey.elementCount].desc.SemanticIndex = sortedSemanticIndices[i]; - ilKey.elements[ilKey.elementCount].desc.Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT; - ilKey.elements[ilKey.elementCount].desc.InputSlot = i; - ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; - ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass; - ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = attributes[i].divisor; - ilKey.elementCount++; - - vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer() : vertexBuffer->getBuffer(); - vertexBufferSerials[i] = bufferStorage ? bufferStorage->getSerial() : vertexBuffer->getSerial(); - vertexStrides[i] = attributes[i].stride; - vertexOffsets[i] = attributes[i].offset; - } - } - - ID3D11InputLayout *inputLayout = NULL; - - InputLayoutMap::iterator i = mInputLayoutMap.find(ilKey); - if (i != mInputLayoutMap.end()) - { - inputLayout = i->second.inputLayout; - i->second.lastUsedTime = mCounter++; - } - else - { - ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable()); - - D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS]; - for (unsigned int j = 0; j < ilKey.elementCount; ++j) - { - descs[j] = ilKey.elements[j].desc; - } - - HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout); - if (FAILED(result)) - { - ERR("Failed to crate input layout, result: 0x%08x", result); - return GL_INVALID_OPERATION; - } - - if (mInputLayoutMap.size() >= kMaxInputLayouts) - { - TRACE("Overflowed the limit of %u input layouts, removing the least recently used " - "to make room.", kMaxInputLayouts); - - InputLayoutMap::iterator leastRecentlyUsed = mInputLayoutMap.begin(); - for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) - { - if (i->second.lastUsedTime < leastRecentlyUsed->second.lastUsedTime) - { - leastRecentlyUsed = i; - } - } - leastRecentlyUsed->second.inputLayout->Release(); - mInputLayoutMap.erase(leastRecentlyUsed); - } - - InputLayoutCounterPair inputCounterPair; - inputCounterPair.inputLayout = inputLayout; - inputCounterPair.lastUsedTime = mCounter++; - - mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair)); - } - - if (inputLayout != mCurrentIL) - { - mDeviceContext->IASetInputLayout(inputLayout); - mCurrentIL = inputLayout; - } - - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - if (vertexBufferSerials[i] != mCurrentBuffers[i] || vertexStrides[i] != mCurrentVertexStrides[i] || - vertexOffsets[i] != mCurrentVertexOffsets[i]) - { - mDeviceContext->IASetVertexBuffers(i, 1, &vertexBuffers[i], &vertexStrides[i], &vertexOffsets[i]); - mCurrentBuffers[i] = vertexBufferSerials[i]; - mCurrentVertexStrides[i] = vertexStrides[i]; - mCurrentVertexOffsets[i] = vertexOffsets[i]; - } - } - - return GL_NO_ERROR; -} - -std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout) -{ - static const unsigned int seed = 0xDEADBEEF; - - std::size_t hash = 0; - MurmurHash3_x86_32(inputLayout.begin(), inputLayout.end() - inputLayout.begin(), seed, &hash); - return hash; -} - -bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b) -{ - if (a.elementCount != b.elementCount) - { - return false; - } - - return std::equal(a.begin(), a.end(), b.begin()); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h deleted file mode 100644 index bb1a8eebcf..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h +++ /dev/null @@ -1,95 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// InputLayoutCache.h: Defines InputLayoutCache, a class that builds and caches -// D3D11 input layouts. - -#ifndef LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ -#define LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ - -#include "libGLESv2/Constants.h" -#include "common/angleutils.h" - -namespace gl -{ -class ProgramBinary; -} - -namespace rx -{ -struct TranslatedAttribute; - -class InputLayoutCache -{ - public: - InputLayoutCache(); - virtual ~InputLayoutCache(); - - void initialize(ID3D11Device *device, ID3D11DeviceContext *context); - void clear(); - void markDirty(); - - GLenum applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], - gl::ProgramBinary *programBinary); - - private: - DISALLOW_COPY_AND_ASSIGN(InputLayoutCache); - - struct InputLayoutElement - { - D3D11_INPUT_ELEMENT_DESC desc; - GLenum glslElementType; - }; - - struct InputLayoutKey - { - unsigned int elementCount; - InputLayoutElement elements[gl::MAX_VERTEX_ATTRIBS]; - - const char *begin() const - { - return reinterpret_cast(&elementCount); - } - - const char *end() const - { - return reinterpret_cast(&elements[elementCount]); - } - }; - - struct InputLayoutCounterPair - { - ID3D11InputLayout *inputLayout; - unsigned long long lastUsedTime; - }; - - ID3D11InputLayout *mCurrentIL; - unsigned int mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS]; - UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS]; - UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS]; - - static std::size_t hashInputLayout(const InputLayoutKey &inputLayout); - static bool compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b); - - typedef std::size_t (*InputLayoutHashFunction)(const InputLayoutKey &); - typedef bool (*InputLayoutEqualityFunction)(const InputLayoutKey &, const InputLayoutKey &); - typedef std::unordered_map InputLayoutMap; - InputLayoutMap mInputLayoutMap; - - static const unsigned int kMaxInputLayouts; - - unsigned long long mCounter; - - ID3D11Device *mDevice; - ID3D11DeviceContext *mDeviceContext; -}; - -} - -#endif // LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Query11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Query11.cpp deleted file mode 100644 index 13210fc929..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Query11.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl. - -#include "libGLESv2/renderer/Query11.h" -#include "libGLESv2/renderer/Renderer11.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -Query11::Query11(rx::Renderer11 *renderer, GLenum type) : QueryImpl(type) -{ - mRenderer = renderer; - mQuery = NULL; -} - -Query11::~Query11() -{ - if (mQuery) - { - mQuery->Release(); - mQuery = NULL; - } -} - -void Query11::begin() -{ - if (mQuery == NULL) - { - D3D11_QUERY_DESC queryDesc; - queryDesc.Query = D3D11_QUERY_OCCLUSION; - queryDesc.MiscFlags = 0; - - if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery))) - { - return gl::error(GL_OUT_OF_MEMORY); - } - } - - mRenderer->getDeviceContext()->Begin(mQuery); -} - -void Query11::end() -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - mRenderer->getDeviceContext()->End(mQuery); - - mStatus = GL_FALSE; - mResult = GL_FALSE; -} - -GLuint Query11::getResult() -{ - if (mQuery != NULL) - { - while (!testQuery()) - { - Sleep(0); - // explicitly check for device loss, some drivers seem to return S_FALSE - // if the device is lost - if (mRenderer->testDeviceLost(true)) - { - return gl::error(GL_OUT_OF_MEMORY, 0); - } - } - } - - return mResult; -} - -GLboolean Query11::isResultAvailable() -{ - if (mQuery != NULL) - { - testQuery(); - } - - return mStatus; -} - -GLboolean Query11::testQuery() -{ - if (mQuery != NULL && mStatus != GL_TRUE) - { - UINT64 numPixels = 0; - HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, &numPixels, sizeof(UINT64), 0); - if (result == S_OK) - { - mStatus = GL_TRUE; - - switch (getType()) - { - case GL_ANY_SAMPLES_PASSED_EXT: - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: - mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; - break; - default: - UNREACHABLE(); - } - } - else if (mRenderer->testDeviceLost(true)) - { - return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); - } - - return mStatus; - } - - return GL_TRUE; // prevent blocking when query is null -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Query11.h b/src/3rdparty/angle/src/libGLESv2/renderer/Query11.h deleted file mode 100644 index 0a03de77ca..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Query11.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Query11.h: Defines the rx::Query11 class which implements rx::QueryImpl. - -#ifndef LIBGLESV2_RENDERER_QUERY11_H_ -#define LIBGLESV2_RENDERER_QUERY11_H_ - -#include "libGLESv2/renderer/QueryImpl.h" - -namespace rx -{ -class Renderer11; - -class Query11 : public QueryImpl -{ - public: - Query11(rx::Renderer11 *renderer, GLenum type); - virtual ~Query11(); - - void begin(); - void end(); - GLuint getResult(); - GLboolean isResultAvailable(); - - private: - DISALLOW_COPY_AND_ASSIGN(Query11); - - GLboolean testQuery(); - - rx::Renderer11 *mRenderer; - ID3D11Query *mQuery; -}; - -} - -#endif // LIBGLESV2_RENDERER_QUERY11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Query9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Query9.cpp deleted file mode 100644 index ef694267dd..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Query9.cpp +++ /dev/null @@ -1,125 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl. - - -#include "libGLESv2/renderer/Query9.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/renderer9_utils.h" -#include "libGLESv2/renderer/Renderer9.h" - -namespace rx -{ - -Query9::Query9(rx::Renderer9 *renderer, GLenum type) : QueryImpl(type) -{ - mRenderer = renderer; - mQuery = NULL; -} - -Query9::~Query9() -{ - if (mQuery) - { - mQuery->Release(); - mQuery = NULL; - } -} - -void Query9::begin() -{ - if (mQuery == NULL) - { - if (FAILED(mRenderer->getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery))) - { - return gl::error(GL_OUT_OF_MEMORY); - } - } - - HRESULT result = mQuery->Issue(D3DISSUE_BEGIN); - ASSERT(SUCCEEDED(result)); -} - -void Query9::end() -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - HRESULT result = mQuery->Issue(D3DISSUE_END); - ASSERT(SUCCEEDED(result)); - - mStatus = GL_FALSE; - mResult = GL_FALSE; -} - -GLuint Query9::getResult() -{ - if (mQuery != NULL) - { - while (!testQuery()) - { - Sleep(0); - // explicitly check for device loss - // some drivers seem to return S_FALSE even if the device is lost - // instead of D3DERR_DEVICELOST like they should - if (mRenderer->testDeviceLost(true)) - { - return gl::error(GL_OUT_OF_MEMORY, 0); - } - } - } - - return mResult; -} - -GLboolean Query9::isResultAvailable() -{ - if (mQuery != NULL) - { - testQuery(); - } - - return mStatus; -} - -GLboolean Query9::testQuery() -{ - if (mQuery != NULL && mStatus != GL_TRUE) - { - DWORD numPixels = 0; - - HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH); - if (hres == S_OK) - { - mStatus = GL_TRUE; - - switch (getType()) - { - case GL_ANY_SAMPLES_PASSED_EXT: - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: - mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; - break; - default: - ASSERT(false); - } - } - else if (d3d9::isDeviceLostError(hres)) - { - mRenderer->notifyDeviceLost(); - return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); - } - - return mStatus; - } - - return GL_TRUE; // prevent blocking when query is null -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Query9.h b/src/3rdparty/angle/src/libGLESv2/renderer/Query9.h deleted file mode 100644 index 47eef89336..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Query9.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Query9.h: Defines the rx::Query9 class which implements rx::QueryImpl. - -#ifndef LIBGLESV2_RENDERER_QUERY9_H_ -#define LIBGLESV2_RENDERER_QUERY9_H_ - -#include "libGLESv2/renderer/QueryImpl.h" - -namespace rx -{ -class Renderer9; - -class Query9 : public QueryImpl -{ - public: - Query9(rx::Renderer9 *renderer, GLenum type); - virtual ~Query9(); - - void begin(); - void end(); - GLuint getResult(); - GLboolean isResultAvailable(); - - private: - DISALLOW_COPY_AND_ASSIGN(Query9); - - GLboolean testQuery(); - - rx::Renderer9 *mRenderer; - IDirect3DQuery9 *mQuery; -}; - -} - -#endif // LIBGLESV2_RENDERER_QUERY9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp deleted file mode 100644 index fd388dfe08..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp +++ /dev/null @@ -1,407 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render -// state objects. - -#include "libGLESv2/renderer/RenderStateCache.h" -#include "libGLESv2/renderer/renderer11_utils.h" - -#include "common/debug.h" -#include "third_party/murmurhash/MurmurHash3.h" - -namespace rx -{ - -// MSDN's documentation of ID3D11Device::CreateBlendState, ID3D11Device::CreateRasterizerState, -// ID3D11Device::CreateDepthStencilState and ID3D11Device::CreateSamplerState claims the maximum -// number of unique states of each type an application can create is 4096 -const unsigned int RenderStateCache::kMaxBlendStates = 4096; -const unsigned int RenderStateCache::kMaxRasterizerStates = 4096; -const unsigned int RenderStateCache::kMaxDepthStencilStates = 4096; -const unsigned int RenderStateCache::kMaxSamplerStates = 4096; - -RenderStateCache::RenderStateCache() : mDevice(NULL), mCounter(0), - mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates), - mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates), - mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates), - mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates) -{ -} - -RenderStateCache::~RenderStateCache() -{ - clear(); -} - -void RenderStateCache::initialize(ID3D11Device *device) -{ - clear(); - mDevice = device; -} - -void RenderStateCache::clear() -{ - for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++) - { - i->second.first->Release(); - } - mBlendStateCache.clear(); - - for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++) - { - i->second.first->Release(); - } - mRasterizerStateCache.clear(); - - for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++) - { - i->second.first->Release(); - } - mDepthStencilStateCache.clear(); - - for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++) - { - i->second.first->Release(); - } - mSamplerStateCache.clear(); -} - -std::size_t RenderStateCache::hashBlendState(const gl::BlendState &blendState) -{ - static const unsigned int seed = 0xABCDEF98; - - std::size_t hash = 0; - MurmurHash3_x86_32(&blendState, sizeof(gl::BlendState), seed, &hash); - return hash; -} - -bool RenderStateCache::compareBlendStates(const gl::BlendState &a, const gl::BlendState &b) -{ - return memcmp(&a, &b, sizeof(gl::BlendState)) == 0; -} - -ID3D11BlendState *RenderStateCache::getBlendState(const gl::BlendState &blendState) -{ - if (!mDevice) - { - ERR("RenderStateCache is not initialized."); - return NULL; - } - - BlendStateMap::iterator i = mBlendStateCache.find(blendState); - if (i != mBlendStateCache.end()) - { - BlendStateCounterPair &state = i->second; - state.second = mCounter++; - return state.first; - } - else - { - if (mBlendStateCache.size() >= kMaxBlendStates) - { - TRACE("Overflowed the limit of %u blend states, removing the least recently used " - "to make room.", kMaxBlendStates); - - BlendStateMap::iterator leastRecentlyUsed = mBlendStateCache.begin(); - for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++) - { - if (i->second.second < leastRecentlyUsed->second.second) - { - leastRecentlyUsed = i; - } - } - leastRecentlyUsed->second.first->Release(); - mBlendStateCache.erase(leastRecentlyUsed); - } - - // Create a new blend state and insert it into the cache - D3D11_BLEND_DESC blendDesc = { 0 }; - blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage; - blendDesc.IndependentBlendEnable = FALSE; - - for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) - { - D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = blendDesc.RenderTarget[i]; - - rtBlend.BlendEnable = blendState.blend; - if (blendState.blend) - { - rtBlend.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false); - rtBlend.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false); - rtBlend.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB); - - rtBlend.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true); - rtBlend.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true); - rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha); - } - - rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendState.colorMaskRed, - blendState.colorMaskGreen, - blendState.colorMaskBlue, - blendState.colorMaskAlpha); - } - - ID3D11BlendState *dx11BlendState = NULL; - HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState); - if (FAILED(result) || !dx11BlendState) - { - ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); - return NULL; - } - - mBlendStateCache.insert(std::make_pair(blendState, std::make_pair(dx11BlendState, mCounter++))); - - return dx11BlendState; - } -} - -std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rasterState) -{ - static const unsigned int seed = 0xABCDEF98; - - std::size_t hash = 0; - MurmurHash3_x86_32(&rasterState, sizeof(RasterizerStateKey), seed, &hash); - return hash; -} - -bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b) -{ - return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0; -} - -ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, - bool scissorEnabled, unsigned int depthSize) -{ - if (!mDevice) - { - ERR("RenderStateCache is not initialized."); - return NULL; - } - - RasterizerStateKey key; - key.rasterizerState = rasterState; - key.scissorEnabled = scissorEnabled; - key.depthSize = depthSize; - - RasterizerStateMap::iterator i = mRasterizerStateCache.find(key); - if (i != mRasterizerStateCache.end()) - { - RasterizerStateCounterPair &state = i->second; - state.second = mCounter++; - return state.first; - } - else - { - if (mRasterizerStateCache.size() >= kMaxRasterizerStates) - { - TRACE("Overflowed the limit of %u rasterizer states, removing the least recently used " - "to make room.", kMaxRasterizerStates); - - RasterizerStateMap::iterator leastRecentlyUsed = mRasterizerStateCache.begin(); - for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++) - { - if (i->second.second < leastRecentlyUsed->second.second) - { - leastRecentlyUsed = i; - } - } - leastRecentlyUsed->second.first->Release(); - mRasterizerStateCache.erase(leastRecentlyUsed); - } - - D3D11_CULL_MODE cullMode = gl_d3d11::ConvertCullMode(rasterState.cullFace, rasterState.cullMode); - - // Disable culling if drawing points - if (rasterState.pointDrawMode) - { - cullMode = D3D11_CULL_NONE; - } - - D3D11_RASTERIZER_DESC rasterDesc; - rasterDesc.FillMode = D3D11_FILL_SOLID; - rasterDesc.CullMode = cullMode; - rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? FALSE: TRUE; - rasterDesc.DepthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast(depthSize)); - rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though. - rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor; - rasterDesc.DepthClipEnable = TRUE; - rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE; - rasterDesc.MultisampleEnable = rasterState.multiSample; - rasterDesc.AntialiasedLineEnable = FALSE; - - ID3D11RasterizerState *dx11RasterizerState = NULL; - HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState); - if (FAILED(result) || !dx11RasterizerState) - { - ERR("Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result); - return NULL; - } - - mRasterizerStateCache.insert(std::make_pair(key, std::make_pair(dx11RasterizerState, mCounter++))); - - return dx11RasterizerState; - } -} - -std::size_t RenderStateCache::hashDepthStencilState(const gl::DepthStencilState &dsState) -{ - static const unsigned int seed = 0xABCDEF98; - - std::size_t hash = 0; - MurmurHash3_x86_32(&dsState, sizeof(gl::DepthStencilState), seed, &hash); - return hash; -} - -bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b) -{ - return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0; -} - -ID3D11DepthStencilState *RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState) -{ - if (!mDevice) - { - ERR("RenderStateCache is not initialized."); - return NULL; - } - - DepthStencilStateMap::iterator i = mDepthStencilStateCache.find(dsState); - if (i != mDepthStencilStateCache.end()) - { - DepthStencilStateCounterPair &state = i->second; - state.second = mCounter++; - return state.first; - } - else - { - if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates) - { - TRACE("Overflowed the limit of %u depth stencil states, removing the least recently used " - "to make room.", kMaxDepthStencilStates); - - DepthStencilStateMap::iterator leastRecentlyUsed = mDepthStencilStateCache.begin(); - for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++) - { - if (i->second.second < leastRecentlyUsed->second.second) - { - leastRecentlyUsed = i; - } - } - leastRecentlyUsed->second.first->Release(); - mDepthStencilStateCache.erase(leastRecentlyUsed); - } - - D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 }; - dsDesc.DepthEnable = dsState.depthTest ? TRUE : FALSE; - dsDesc.DepthWriteMask = gl_d3d11::ConvertDepthMask(dsState.depthMask); - dsDesc.DepthFunc = gl_d3d11::ConvertComparison(dsState.depthFunc); - dsDesc.StencilEnable = dsState.stencilTest ? TRUE : FALSE; - dsDesc.StencilReadMask = gl_d3d11::ConvertStencilMask(dsState.stencilMask); - dsDesc.StencilWriteMask = gl_d3d11::ConvertStencilMask(dsState.stencilWritemask); - dsDesc.FrontFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilFail); - dsDesc.FrontFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthFail); - dsDesc.FrontFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthPass); - dsDesc.FrontFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilFunc); - dsDesc.BackFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackFail); - dsDesc.BackFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthFail); - dsDesc.BackFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthPass); - dsDesc.BackFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilBackFunc); - - ID3D11DepthStencilState *dx11DepthStencilState = NULL; - HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState); - if (FAILED(result) || !dx11DepthStencilState) - { - ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); - return NULL; - } - - mDepthStencilStateCache.insert(std::make_pair(dsState, std::make_pair(dx11DepthStencilState, mCounter++))); - - return dx11DepthStencilState; - } -} - -std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState) -{ - static const unsigned int seed = 0xABCDEF98; - - std::size_t hash = 0; - MurmurHash3_x86_32(&samplerState, sizeof(gl::SamplerState), seed, &hash); - return hash; -} - -bool RenderStateCache::compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b) -{ - return memcmp(&a, &b, sizeof(gl::SamplerState)) == 0; -} - -ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &samplerState) -{ - if (!mDevice) - { - ERR("RenderStateCache is not initialized."); - return NULL; - } - - SamplerStateMap::iterator i = mSamplerStateCache.find(samplerState); - if (i != mSamplerStateCache.end()) - { - SamplerStateCounterPair &state = i->second; - state.second = mCounter++; - return state.first; - } - else - { - if (mSamplerStateCache.size() >= kMaxSamplerStates) - { - TRACE("Overflowed the limit of %u sampler states, removing the least recently used " - "to make room.", kMaxSamplerStates); - - SamplerStateMap::iterator leastRecentlyUsed = mSamplerStateCache.begin(); - for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++) - { - if (i->second.second < leastRecentlyUsed->second.second) - { - leastRecentlyUsed = i; - } - } - leastRecentlyUsed->second.first->Release(); - mSamplerStateCache.erase(leastRecentlyUsed); - } - - D3D11_SAMPLER_DESC samplerDesc; - samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter, samplerState.maxAnisotropy); - samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS); - samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT); - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.MipLODBias = static_cast(samplerState.lodOffset); - samplerDesc.MaxAnisotropy = samplerState.maxAnisotropy; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; - samplerDesc.BorderColor[0] = 0.0f; - samplerDesc.BorderColor[1] = 0.0f; - samplerDesc.BorderColor[2] = 0.0f; - samplerDesc.BorderColor[3] = 0.0f; - samplerDesc.MinLOD = gl_d3d11::ConvertMinLOD(samplerState.minFilter, samplerState.lodOffset); - samplerDesc.MaxLOD = mDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_0 - ? gl_d3d11::ConvertMaxLOD(samplerState.minFilter, samplerState.lodOffset) : FLT_MAX; - - ID3D11SamplerState *dx11SamplerState = NULL; - HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState); - if (FAILED(result) || !dx11SamplerState) - { - ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); - return NULL; - } - - mSamplerStateCache.insert(std::make_pair(samplerState, std::make_pair(dx11SamplerState, mCounter++))); - - return dx11SamplerState; - } -} - -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.h deleted file mode 100644 index f8b5111de4..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.h +++ /dev/null @@ -1,101 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderStateCache.h: Defines rx::RenderStateCache, a cache of Direct3D render -// state objects. - -#ifndef LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ -#define LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ - -#include "libGLESv2/angletypes.h" -#include "common/angleutils.h" - -namespace rx -{ - -class RenderStateCache -{ - public: - RenderStateCache(); - virtual ~RenderStateCache(); - - void initialize(ID3D11Device *device); - void clear(); - - // Increments refcount on the returned blend state, Release() must be called. - ID3D11BlendState *getBlendState(const gl::BlendState &blendState); - ID3D11RasterizerState *getRasterizerState(const gl::RasterizerState &rasterState, - bool scissorEnabled, unsigned int depthSize); - ID3D11DepthStencilState *getDepthStencilState(const gl::DepthStencilState &dsState); - ID3D11SamplerState *getSamplerState(const gl::SamplerState &samplerState); - - private: - DISALLOW_COPY_AND_ASSIGN(RenderStateCache); - - unsigned long long mCounter; - - // Blend state cache - static std::size_t hashBlendState(const gl::BlendState &blendState); - static bool compareBlendStates(const gl::BlendState &a, const gl::BlendState &b); - static const unsigned int kMaxBlendStates; - - typedef std::size_t (*BlendStateHashFunction)(const gl::BlendState &); - typedef bool (*BlendStateEqualityFunction)(const gl::BlendState &, const gl::BlendState &); - typedef std::pair BlendStateCounterPair; - typedef std::unordered_map BlendStateMap; - BlendStateMap mBlendStateCache; - - // Rasterizer state cache - struct RasterizerStateKey - { - gl::RasterizerState rasterizerState; - bool scissorEnabled; - unsigned int depthSize; - }; - static std::size_t hashRasterizerState(const RasterizerStateKey &rasterState); - static bool compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b); - static const unsigned int kMaxRasterizerStates; - - typedef std::size_t (*RasterizerStateHashFunction)(const RasterizerStateKey &); - typedef bool (*RasterizerStateEqualityFunction)(const RasterizerStateKey &, const RasterizerStateKey &); - typedef std::pair RasterizerStateCounterPair; - typedef std::unordered_map RasterizerStateMap; - RasterizerStateMap mRasterizerStateCache; - - // Depth stencil state cache - static std::size_t hashDepthStencilState(const gl::DepthStencilState &dsState); - static bool compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b); - static const unsigned int kMaxDepthStencilStates; - - typedef std::size_t (*DepthStencilStateHashFunction)(const gl::DepthStencilState &); - typedef bool (*DepthStencilStateEqualityFunction)(const gl::DepthStencilState &, const gl::DepthStencilState &); - typedef std::pair DepthStencilStateCounterPair; - typedef std::unordered_map DepthStencilStateMap; - DepthStencilStateMap mDepthStencilStateCache; - - // Sample state cache - static std::size_t hashSamplerState(const gl::SamplerState &samplerState); - static bool compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b); - static const unsigned int kMaxSamplerStates; - - typedef std::size_t (*SamplerStateHashFunction)(const gl::SamplerState &); - typedef bool (*SamplerStateEqualityFunction)(const gl::SamplerState &, const gl::SamplerState &); - typedef std::pair SamplerStateCounterPair; - typedef std::unordered_map SamplerStateMap; - SamplerStateMap mSamplerStateCache; - - ID3D11Device *mDevice; -}; - -} - -#endif // LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp deleted file mode 100644 index 2667cc6fa7..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp +++ /dev/null @@ -1,355 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers -// retained by Renderbuffers. - -#include "libGLESv2/renderer/RenderTarget11.h" -#include "libGLESv2/renderer/Renderer11.h" - -#include "libGLESv2/renderer/renderer11_utils.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -static unsigned int getRTVSubresourceIndex(ID3D11Texture2D *texture, ID3D11RenderTargetView *view) -{ - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - view->GetDesc(&rtvDesc); - - D3D11_TEXTURE2D_DESC texDesc; - texture->GetDesc(&texDesc); - - unsigned int mipSlice = 0; - unsigned int arraySlice = 0; - unsigned int mipLevels = texDesc.MipLevels; - - switch (rtvDesc.ViewDimension) - { - case D3D11_RTV_DIMENSION_TEXTURE1D: - mipSlice = rtvDesc.Texture1D.MipSlice; - arraySlice = 0; - break; - - case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: - mipSlice = rtvDesc.Texture1DArray.MipSlice; - arraySlice = rtvDesc.Texture1DArray.FirstArraySlice; - break; - - case D3D11_RTV_DIMENSION_TEXTURE2D: - mipSlice = rtvDesc.Texture2D.MipSlice; - arraySlice = 0; - break; - - case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: - mipSlice = rtvDesc.Texture2DArray.MipSlice; - arraySlice = rtvDesc.Texture2DArray.FirstArraySlice; - break; - - case D3D11_RTV_DIMENSION_TEXTURE2DMS: - mipSlice = 0; - arraySlice = 0; - break; - - case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: - mipSlice = 0; - arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice; - break; - - case D3D11_RTV_DIMENSION_TEXTURE3D: - mipSlice = rtvDesc.Texture3D.MipSlice; - arraySlice = 0; - break; - - case D3D11_RTV_DIMENSION_UNKNOWN: - case D3D11_RTV_DIMENSION_BUFFER: - UNIMPLEMENTED(); - break; - - default: - UNREACHABLE(); - break; - } - - return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); -} - -static unsigned int getDSVSubresourceIndex(ID3D11Texture2D *texture, ID3D11DepthStencilView *view) -{ - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - view->GetDesc(&dsvDesc); - - D3D11_TEXTURE2D_DESC texDesc; - texture->GetDesc(&texDesc); - - unsigned int mipSlice = 0; - unsigned int arraySlice = 0; - unsigned int mipLevels = texDesc.MipLevels; - - switch (dsvDesc.ViewDimension) - { - case D3D11_DSV_DIMENSION_TEXTURE1D: - mipSlice = dsvDesc.Texture1D.MipSlice; - arraySlice = 0; - break; - - case D3D11_DSV_DIMENSION_TEXTURE1DARRAY: - mipSlice = dsvDesc.Texture1DArray.MipSlice; - arraySlice = dsvDesc.Texture1DArray.FirstArraySlice; - break; - - case D3D11_DSV_DIMENSION_TEXTURE2D: - mipSlice = dsvDesc.Texture2D.MipSlice; - arraySlice = 0; - break; - - case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: - mipSlice = dsvDesc.Texture2DArray.MipSlice; - arraySlice = dsvDesc.Texture2DArray.FirstArraySlice; - break; - - case D3D11_DSV_DIMENSION_TEXTURE2DMS: - mipSlice = 0; - arraySlice = 0; - break; - - case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: - mipSlice = 0; - arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice; - break; - - case D3D11_RTV_DIMENSION_UNKNOWN: - UNIMPLEMENTED(); - break; - - default: - UNREACHABLE(); - break; - } - - return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); -} - -RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height) -{ - mRenderer = Renderer11::makeRenderer11(renderer); - mTexture = tex; - mRenderTarget = rtv; - mDepthStencil = NULL; - mShaderResource = srv; - mSubresourceIndex = 0; - - if (mRenderTarget && mTexture) - { - D3D11_RENDER_TARGET_VIEW_DESC desc; - mRenderTarget->GetDesc(&desc); - - D3D11_TEXTURE2D_DESC texDesc; - mTexture->GetDesc(&texDesc); - - mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget); - mWidth = width; - mHeight = height; - mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0; - - mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); - mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); - } -} - -RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height) -{ - mRenderer = Renderer11::makeRenderer11(renderer); - mTexture = tex; - mRenderTarget = NULL; - mDepthStencil = dsv; - mShaderResource = srv; - mSubresourceIndex = 0; - - if (mDepthStencil && mTexture) - { - D3D11_DEPTH_STENCIL_VIEW_DESC desc; - mDepthStencil->GetDesc(&desc); - - D3D11_TEXTURE2D_DESC texDesc; - mTexture->GetDesc(&texDesc); - - mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil); - mWidth = width; - mHeight = height; - mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0; - - mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); - mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); - } -} - -RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth) -{ - mRenderer = Renderer11::makeRenderer11(renderer); - mTexture = NULL; - mRenderTarget = NULL; - mDepthStencil = NULL; - mShaderResource = NULL; - - DXGI_FORMAT requestedFormat = gl_d3d11::ConvertRenderbufferFormat(format); - - int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples); - if (supportedSamples < 0) - { - gl::error(GL_OUT_OF_MEMORY); - return; - } - - if (width > 0 && height > 0) - { - // Create texture resource - D3D11_TEXTURE2D_DESC desc; - desc.Width = width; - desc.Height = height; - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = requestedFormat; - desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - desc.BindFlags = (depth ? D3D11_BIND_DEPTH_STENCIL : (D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)); - - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); - - if (result == E_OUTOFMEMORY) - { - gl::error(GL_OUT_OF_MEMORY); - return; - } - ASSERT(SUCCEEDED(result)); - - if (depth) - { - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = requestedFormat; - dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; - dsvDesc.Texture2D.MipSlice = 0; - dsvDesc.Flags = 0; - result = device->CreateDepthStencilView(mTexture, &dsvDesc, &mDepthStencil); - - if (result == E_OUTOFMEMORY) - { - mTexture->Release(); - mTexture = NULL; - gl::error(GL_OUT_OF_MEMORY); - } - ASSERT(SUCCEEDED(result)); - } - else - { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = requestedFormat; - rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; - rtvDesc.Texture2D.MipSlice = 0; - result = device->CreateRenderTargetView(mTexture, &rtvDesc, &mRenderTarget); - - if (result == E_OUTOFMEMORY) - { - mTexture->Release(); - mTexture = NULL; - gl::error(GL_OUT_OF_MEMORY); - return; - } - ASSERT(SUCCEEDED(result)); - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = requestedFormat; - srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; - srvDesc.Texture2D.MostDetailedMip = 0; - srvDesc.Texture2D.MipLevels = 1; - result = device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResource); - - if (result == E_OUTOFMEMORY) - { - mTexture->Release(); - mTexture = NULL; - mRenderTarget->Release(); - mRenderTarget = NULL; - gl::error(GL_OUT_OF_MEMORY); - return; - } - ASSERT(SUCCEEDED(result)); - } - } - - mWidth = width; - mHeight = height; - mInternalFormat = format; - mSamples = supportedSamples; - mActualFormat = d3d11_gl::ConvertTextureInternalFormat(requestedFormat); - mSubresourceIndex = D3D11CalcSubresource(0, 0, 1); -} - -RenderTarget11::~RenderTarget11() -{ - if (mTexture) - { - mTexture->Release(); - mTexture = NULL; - } - - if (mRenderTarget) - { - mRenderTarget->Release(); - mRenderTarget = NULL; - } - - if (mDepthStencil) - { - mDepthStencil->Release(); - mDepthStencil = NULL; - } - - if (mShaderResource) - { - mShaderResource->Release(); - mShaderResource = NULL; - } -} - -RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget11*, target)); - return static_cast(target); -} - -ID3D11Texture2D *RenderTarget11::getTexture() const -{ - return mTexture; -} - -ID3D11RenderTargetView *RenderTarget11::getRenderTargetView() const -{ - return mRenderTarget; -} - -ID3D11DepthStencilView *RenderTarget11::getDepthStencilView() const -{ - return mDepthStencil; -} - -ID3D11ShaderResourceView *RenderTarget11::getShaderResourceView() const -{ - return mShaderResource; -} - -unsigned int RenderTarget11::getSubresourceIndex() const -{ - return mSubresourceIndex; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.h deleted file mode 100644 index 97827f2639..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderTarget11.h: Defines a DX11-specific wrapper for ID3D11View pointers -// retained by Renderbuffers. - -#ifndef LIBGLESV2_RENDERER_RENDERTARGET11_H_ -#define LIBGLESV2_RENDERER_RENDERTARGET11_H_ - -#include "libGLESv2/renderer/RenderTarget.h" - -namespace rx -{ -class Renderer; -class Renderer11; - -class RenderTarget11 : public RenderTarget -{ - public: - RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height); - RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height); - RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth); - virtual ~RenderTarget11(); - - static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget); - - ID3D11Texture2D *getTexture() const; - ID3D11RenderTargetView *getRenderTargetView() const; - ID3D11DepthStencilView *getDepthStencilView() const; - ID3D11ShaderResourceView *getShaderResourceView() const; - - unsigned int getSubresourceIndex() const; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderTarget11); - - unsigned int mSubresourceIndex; - ID3D11Texture2D *mTexture; - ID3D11RenderTargetView *mRenderTarget; - ID3D11DepthStencilView *mDepthStencil; - ID3D11ShaderResourceView *mShaderResource; - - Renderer11 *mRenderer; -}; - -} - -#endif LIBGLESV2_RENDERER_RENDERTARGET11_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget9.cpp deleted file mode 100644 index a84c709059..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget9.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9 -// pointers retained by renderbuffers. - -#include "libGLESv2/renderer/RenderTarget9.h" -#include "libGLESv2/renderer/Renderer9.h" - -#include "libGLESv2/renderer/renderer9_utils.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -RenderTarget9::RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface) -{ - mRenderer = Renderer9::makeRenderer9(renderer); - mRenderTarget = surface; - - if (mRenderTarget) - { - D3DSURFACE_DESC description; - mRenderTarget->GetDesc(&description); - - mWidth = description.Width; - mHeight = description.Height; - - mInternalFormat = d3d9_gl::GetEquivalentFormat(description.Format); - mActualFormat = d3d9_gl::GetEquivalentFormat(description.Format); - mSamples = d3d9_gl::GetSamplesFromMultisampleType(description.MultiSampleType); - } -} - -RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples) -{ - mRenderer = Renderer9::makeRenderer9(renderer); - mRenderTarget = NULL; - - D3DFORMAT requestedFormat = gl_d3d9::ConvertRenderbufferFormat(format); - int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples); - - if (supportedSamples == -1) - { - gl::error(GL_OUT_OF_MEMORY); - - return; - } - - HRESULT result = D3DERR_INVALIDCALL; - - if (width > 0 && height > 0) - { - if (requestedFormat == D3DFMT_D24S8) - { - result = mRenderer->getDevice()->CreateDepthStencilSurface(width, height, requestedFormat, - gl_d3d9::GetMultisampleTypeFromSamples(supportedSamples), - 0, FALSE, &mRenderTarget, NULL); - } - else - { - result = mRenderer->getDevice()->CreateRenderTarget(width, height, requestedFormat, - gl_d3d9::GetMultisampleTypeFromSamples(supportedSamples), - 0, FALSE, &mRenderTarget, NULL); - } - - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) - { - gl::error(GL_OUT_OF_MEMORY); - - return; - } - - ASSERT(SUCCEEDED(result)); - } - - mWidth = width; - mHeight = height; - mInternalFormat = format; - mSamples = supportedSamples; - mActualFormat = d3d9_gl::GetEquivalentFormat(requestedFormat); -} - -RenderTarget9::~RenderTarget9() -{ - if (mRenderTarget) - { - mRenderTarget->Release(); - } -} - -RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget9*, target)); - return static_cast(target); -} - -IDirect3DSurface9 *RenderTarget9::getSurface() -{ - // Caller is responsible for releasing the returned surface reference. - if (mRenderTarget) - { - mRenderTarget->AddRef(); - } - - return mRenderTarget; -} - -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget9.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget9.h deleted file mode 100644 index faf8ad1c6d..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget9.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderTarget9.h: Defines a D3D9-specific wrapper for IDirect3DSurface9 pointers -// retained by Renderbuffers. - -#ifndef LIBGLESV2_RENDERER_RENDERTARGET9_H_ -#define LIBGLESV2_RENDERER_RENDERTARGET9_H_ - -#include "libGLESv2/renderer/RenderTarget.h" - -namespace rx -{ -class Renderer; -class Renderer9; - -class RenderTarget9 : public RenderTarget -{ - public: - RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface); - RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples); - virtual ~RenderTarget9(); - - static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget); - IDirect3DSurface9 *getSurface(); - - private: - DISALLOW_COPY_AND_ASSIGN(RenderTarget9); - - IDirect3DSurface9 *mRenderTarget; - - Renderer9 *mRenderer; -}; - -} - -#endif // LIBGLESV2_RENDERER_RENDERTARGET9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp index 39fd0f41f0..5278113811 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp @@ -11,35 +11,26 @@ #include "libGLESv2/main.h" #include "libGLESv2/Program.h" #include "libGLESv2/renderer/Renderer.h" -#ifndef ANGLE_ENABLE_D3D11 -#include "libGLESv2/renderer/Renderer9.h" -#else -#include "libGLESv2/renderer/Renderer11.h" +#if defined(ANGLE_ENABLE_D3D9) +# include "libGLESv2/renderer/d3d9/Renderer9.h" +#endif +#if defined(ANGLE_ENABLE_D3D11) +# include "libGLESv2/renderer/d3d11/Renderer11.h" #endif #include "libGLESv2/utilities.h" #include "third_party/trace_event/trace_event.h" -#if !defined(ANGLE_ENABLE_D3D11) -// Enables use of the Direct3D 11 API for a default display, when available -#define ANGLE_ENABLE_D3D11 0 -#endif - #ifndef D3DERR_OUTOFVIDEOMEMORY #define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT(1, 0x876, 380) #endif -#ifndef D3DCOMPILER_DLL -#define D3DCOMPILER_DLL L"d3dcompiler_43.dll" // Lowest common denominator -#endif +#if defined(__MINGW32__) || defined(ANGLE_OS_WINPHONE) -#ifndef QT_D3DCOMPILER_DLL -#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL -#endif +#ifndef D3DCOMPILER_DLL -#if defined(__MINGW32__) || defined(ANGLE_OS_WINPHONE) +// Add define + typedefs for older MinGW-w64 headers (pre 5783) -//Add define + typedefs for older MinGW-w64 headers (pre 5783) -//Also define these on Windows Phone, which doesn't have a shader compiler +#define D3DCOMPILER_DLL L"d3dcompiler_43.dll" HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename, const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, @@ -48,8 +39,14 @@ typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); +#endif // D3DCOMPILER_DLL + #endif // __MINGW32__ || ANGLE_OS_WINPHONE +#ifndef QT_D3DCOMPILER_DLL +#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL +#endif + namespace rx { @@ -82,7 +79,8 @@ bool Renderer::initializeCompiler() break; } } -#else +#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES + // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL #if !defined(ANGLE_OS_WINRT) const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL"); @@ -109,15 +107,11 @@ bool Renderer::initializeCompiler() // Load the first available known compiler DLL for (int i = 0; compilerDlls[i]; ++i) { -#if !defined(ANGLE_OS_WINRT) + // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. mD3dCompilerModule = LoadLibrary(compilerDlls[i]); -#else - mD3dCompilerModule = LoadPackagedLibrary(compilerDlls[i], NULL); -#endif if (mD3dCompilerModule) break; } -#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES if (!mD3dCompilerModule) { @@ -230,18 +224,46 @@ ShaderBlob *Renderer::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, co extern "C" { -rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayType displayId) +rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType displayId) { rx::Renderer *renderer = NULL; EGLint status = EGL_BAD_ALLOC; -#if ANGLE_ENABLE_D3D11 - renderer = new rx::Renderer11(display, hDc); -#else - bool softwareDevice = (displayId == EGL_SOFTWARE_DISPLAY_ANGLE); - renderer = new rx::Renderer9(display, hDc, softwareDevice); +#if defined(ANGLE_OS_WINRT) + if (displayId == EGL_DEFAULT_DISPLAY) + displayId = EGL_D3D11_ONLY_DISPLAY_ANGLE; #endif +#if defined(ANGLE_ENABLE_D3D11) + if (displayId == EGL_DEFAULT_DISPLAY || + displayId == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE) + { + renderer = new rx::Renderer11(display); + + if (renderer) + { + status = renderer->initialize(); + } + + if (status == EGL_SUCCESS) + { + return renderer; + } + else if (displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE) + { + return NULL; + } + + // Failed to create a D3D11 renderer, try creating a D3D9 renderer + delete renderer; + } +#endif // ANGLE_ENABLE_D3D11 + +#if defined(ANGLE_ENABLE_D3D9) + bool softwareDevice = (displayId == EGL_SOFTWARE_DISPLAY_ANGLE); + renderer = new rx::Renderer9(display, displayId, softwareDevice); + if (renderer) { status = renderer->initialize(); @@ -251,6 +273,7 @@ rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayT { return renderer; } +#endif // ANGLE_ENABLE_D3D9 return NULL; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h index ac67c27e71..79578b2458 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h @@ -14,30 +14,6 @@ #include "libGLESv2/Uniform.h" #include "libGLESv2/angletypes.h" -#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL0 -#define D3DCOMPILE_OPTIMIZATION_LEVEL0 (1 << 14) -#endif -#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL1 -#define D3DCOMPILE_OPTIMIZATION_LEVEL1 0 -#endif -#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL2 -#define D3DCOMPILE_OPTIMIZATION_LEVEL2 ((1 << 14) | (1 << 15)) -#endif -#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL3 -#define D3DCOMPILE_OPTIMIZATION_LEVEL3 (1 << 15) -#endif -#ifndef D3DCOMPILE_DEBUG -#define D3DCOMPILE_DEBUG (1 << 0) -#endif -#ifndef D3DCOMPILE_SKIP_OPTIMIZATION -#define D3DCOMPILE_SKIP_OPTIMIZATION (1 << 2) -#endif -#ifndef D3DCOMPILE_AVOID_FLOW_CONTROL -#define D3DCOMPILE_AVOID_FLOW_CONTROL (1 << 9) -#endif -#ifndef D3DCOMPILE_PREFER_FLOW_CONTROL -#define D3DCOMPILE_PREFER_FLOW_CONTROL (1 << 10) -#endif #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 #endif @@ -118,6 +94,12 @@ enum ShaderType SHADER_GEOMETRY }; +enum D3DWorkaroundType +{ + ANGLE_D3D_WORKAROUND_NONE, + ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER +}; + class Renderer { public: @@ -138,7 +120,7 @@ class Renderer virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0; virtual void setRasterizerState(const gl::RasterizerState &rasterState) = 0; - virtual void setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, + virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask) = 0; virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, int stencilBackRef, bool frontFaceCCW) = 0; @@ -232,7 +214,7 @@ class Renderer // Shader operations virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type) = 0; - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type) = 0; + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) = 0; // Image operations virtual Image *createImage() = 0; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp deleted file mode 100644 index f83e9e91ce..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp +++ /dev/null @@ -1,3672 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer. - -#include "libGLESv2/main.h" -#include "libGLESv2/utilities.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/RenderBuffer.h" -#include "libGLESv2/renderer/Renderer11.h" -#include "libGLESv2/renderer/RenderTarget11.h" -#include "libGLESv2/renderer/renderer11_utils.h" -#include "libGLESv2/renderer/ShaderExecutable11.h" -#include "libGLESv2/renderer/SwapChain11.h" -#include "libGLESv2/renderer/Image11.h" -#include "libGLESv2/renderer/VertexBuffer11.h" -#include "libGLESv2/renderer/IndexBuffer11.h" -#include "libGLESv2/renderer/BufferStorage11.h" -#include "libGLESv2/renderer/VertexDataManager.h" -#include "libGLESv2/renderer/IndexDataManager.h" -#include "libGLESv2/renderer/TextureStorage11.h" -#include "libGLESv2/renderer/Query11.h" -#include "libGLESv2/renderer/Fence11.h" - -#include "libGLESv2/renderer/shaders/compiled/passthrough11vs.h" -#include "libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h" -#include "libGLESv2/renderer/shaders/compiled/passthroughrgb11ps.h" -#include "libGLESv2/renderer/shaders/compiled/passthroughlum11ps.h" -#include "libGLESv2/renderer/shaders/compiled/passthroughlumalpha11ps.h" - -#include "libGLESv2/renderer/shaders/compiled/clear11vs.h" -#include "libGLESv2/renderer/shaders/compiled/clearsingle11ps.h" -#include "libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h" - -#include "libEGL/Display.h" - -#ifdef _DEBUG -// this flag enables suppressing some spurious warnings that pop up in certain WebGL samples -// and conformance tests. to enable all warnings, remove this define. -#define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1 -#endif - -namespace rx -{ -static const DXGI_FORMAT RenderTargetFormats[] = - { - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM - }; - -static const DXGI_FORMAT DepthStencilFormats[] = - { - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_D24_UNORM_S8_UINT, - DXGI_FORMAT_D16_UNORM - }; - -enum -{ - MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 -}; - -Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc(hDc) -{ - mVertexDataManager = NULL; - mIndexDataManager = NULL; - - mLineLoopIB = NULL; - mTriangleFanIB = NULL; - - mCopyResourcesInitialized = false; - mCopyVB = NULL; - mCopySampler = NULL; - mCopyIL = NULL; - mCopyVS = NULL; - mCopyRGBAPS = NULL; - mCopyRGBPS = NULL; - mCopyLumPS = NULL; - mCopyLumAlphaPS = NULL; - - mClearResourcesInitialized = false; - mClearVB = NULL; - mClearIL = NULL; - mClearVS = NULL; - mClearSinglePS = NULL; - mClearMultiplePS = NULL; - mClearScissorRS = NULL; - mClearNoScissorRS = NULL; - - mSyncQuery = NULL; - - mD3d11Module = NULL; - mDxgiModule = NULL; - - mDeviceLost = false; - - mMaxSupportedSamples = 0; - - mDevice = NULL; - mDeviceContext = NULL; - mDxgiAdapter = NULL; - mDxgiFactory = NULL; - - mDriverConstantBufferVS = NULL; - mDriverConstantBufferPS = NULL; - - mBGRATextureSupport = false; - - mIsGeometryShaderActive = false; -} - -Renderer11::~Renderer11() -{ - release(); -} - -Renderer11 *Renderer11::makeRenderer11(Renderer *renderer) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer11*, renderer)); - return static_cast(renderer); -} - -#ifndef __d3d11_1_h__ -#define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081) -#endif - -EGLint Renderer11::initialize() -{ - if (!initializeCompiler()) - { - return EGL_NOT_INITIALIZED; - } - -#if !defined(ANGLE_OS_WINRT) - mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); - mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); - - if (mD3d11Module == NULL || mDxgiModule == NULL) - { - ERR("Could not load D3D11 or DXGI library - aborting!\n"); - return EGL_NOT_INITIALIZED; - } - - // create the D3D11 device - ASSERT(mDevice == NULL); - PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); - - if (D3D11CreateDevice == NULL) - { - ERR("Could not retrieve D3D11CreateDevice address - aborting!\n"); - return EGL_NOT_INITIALIZED; - } -#endif - - D3D_FEATURE_LEVEL featureLevels[] = - { - D3D_FEATURE_LEVEL_11_1, - D3D_FEATURE_LEVEL_11_0, - D3D_FEATURE_LEVEL_10_1, - D3D_FEATURE_LEVEL_10_0, - D3D_FEATURE_LEVEL_9_3, - D3D_FEATURE_LEVEL_9_2, - D3D_FEATURE_LEVEL_9_1, - }; - - HRESULT result = S_OK; - -#ifdef _DEBUG - result = D3D11CreateDevice(NULL, - D3D_DRIVER_TYPE_HARDWARE, - NULL, - D3D11_CREATE_DEVICE_DEBUG, - featureLevels, - ArraySize(featureLevels), - D3D11_SDK_VERSION, - &mDevice, - &mFeatureLevel, - &mDeviceContext); - - if (!mDevice || FAILED(result)) - { - ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n"); - } - - if (!mDevice || FAILED(result)) -#endif - { - result = D3D11CreateDevice(NULL, - D3D_DRIVER_TYPE_HARDWARE, - NULL, - 0, - featureLevels, - ArraySize(featureLevels), - D3D11_SDK_VERSION, - &mDevice, - &mFeatureLevel, - &mDeviceContext); - - if (!mDevice || FAILED(result)) - { - ERR("Could not create D3D11 device - aborting!\n"); - return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer - } - } - -#if !defined(ANGLE_OS_WINRT) - IDXGIDevice *dxgiDevice = NULL; -#else - IDXGIDevice1 *dxgiDevice = NULL; -#endif - result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice)); - - if (FAILED(result)) - { - ERR("Could not query DXGI device - aborting!\n"); - return EGL_NOT_INITIALIZED; - } - - result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter); - - if (FAILED(result)) - { - ERR("Could not retrieve DXGI adapter - aborting!\n"); - return EGL_NOT_INITIALIZED; - } - - dxgiDevice->Release(); - - mDxgiAdapter->GetDesc(&mAdapterDescription); - memset(mDescription, 0, sizeof(mDescription)); - wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1); - - result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory); - - if (!mDxgiFactory || FAILED(result)) - { - ERR("Could not create DXGI factory - aborting!\n"); - return EGL_NOT_INITIALIZED; - } - - // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log -#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) - ID3D11InfoQueue *infoQueue; - result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue); - - if (SUCCEEDED(result)) - { - D3D11_MESSAGE_ID hideMessages[] = - { - D3D11_MESSAGE_ID_DEVICE_OMSETRENDERTARGETS_HAZARD, - D3D11_MESSAGE_ID_DEVICE_PSSETSHADERRESOURCES_HAZARD, - D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET - }; - - D3D11_INFO_QUEUE_FILTER filter = {0}; - filter.DenyList.NumIDs = ArraySize(hideMessages); - filter.DenyList.pIDList = hideMessages; - - infoQueue->AddStorageFilterEntries(&filter); - - infoQueue->Release(); - } -#endif - - unsigned int maxSupportedSamples = 0; - unsigned int rtFormatCount = ArraySize(RenderTargetFormats); - unsigned int dsFormatCount = ArraySize(DepthStencilFormats); - for (unsigned int i = 0; i < rtFormatCount + dsFormatCount; ++i) - { - DXGI_FORMAT format = (i < rtFormatCount) ? RenderTargetFormats[i] : DepthStencilFormats[i - rtFormatCount]; - if (format != DXGI_FORMAT_UNKNOWN) - { - UINT formatSupport; - result = mDevice->CheckFormatSupport(format, &formatSupport); - if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET)) - { - MultisampleSupportInfo supportInfo; - - for (unsigned int j = 1; j <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; j++) - { - result = mDevice->CheckMultisampleQualityLevels(format, j, &supportInfo.qualityLevels[j - 1]); - if (SUCCEEDED(result) && supportInfo.qualityLevels[j - 1] > 0) - { - maxSupportedSamples = std::max(j, maxSupportedSamples); - } - else - { - supportInfo.qualityLevels[j - 1] = 0; - } - } - - mMultisampleSupportMap.insert(std::make_pair(format, supportInfo)); - } - } - } - mMaxSupportedSamples = maxSupportedSamples; - - initializeDevice(); - - // BGRA texture support is optional in feature levels 10 and 10_1 - UINT formatSupport; - result = mDevice->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &formatSupport); - if (FAILED(result)) - { - ERR("Error checking BGRA format support: 0x%08X", result); - } - else - { - const int flags = (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET); - mBGRATextureSupport = (formatSupport & flags) == flags; - } - - // Check floating point texture support - static const unsigned int requiredTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE; - static const unsigned int requiredRenderableFlags = D3D11_FORMAT_SUPPORT_RENDER_TARGET; - static const unsigned int requiredFilterFlags = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE; - - DXGI_FORMAT float16Formats[] = - { - DXGI_FORMAT_R16_FLOAT, - DXGI_FORMAT_R16G16_FLOAT, - DXGI_FORMAT_R16G16B16A16_FLOAT, - }; - - DXGI_FORMAT float32Formats[] = - { - DXGI_FORMAT_R32_FLOAT, - DXGI_FORMAT_R32G32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT, - }; - - mFloat16TextureSupport = true; - mFloat16FilterSupport = true; - mFloat16RenderSupport = true; - for (unsigned int i = 0; i < ArraySize(float16Formats); i++) - { - if (SUCCEEDED(mDevice->CheckFormatSupport(float16Formats[i], &formatSupport))) - { - mFloat16TextureSupport = mFloat16TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags; - mFloat16FilterSupport = mFloat16FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags; - mFloat16RenderSupport = mFloat16RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags; - } - else - { - mFloat16TextureSupport = false; - mFloat16RenderSupport = false; - mFloat16FilterSupport = false; - } - } - - mFloat32TextureSupport = true; - mFloat32FilterSupport = true; - mFloat32RenderSupport = true; - for (unsigned int i = 0; i < ArraySize(float32Formats); i++) - { - if (SUCCEEDED(mDevice->CheckFormatSupport(float32Formats[i], &formatSupport))) - { - mFloat32TextureSupport = mFloat32TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags; - mFloat32FilterSupport = mFloat32FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags; - mFloat32RenderSupport = mFloat32RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags; - } - else - { - mFloat32TextureSupport = false; - mFloat32FilterSupport = false; - mFloat32RenderSupport = false; - } - } - - // Check compressed texture support - const unsigned int requiredCompressedTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D; - - if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC1_UNORM, &formatSupport))) - { - mDXT1TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; - } - else - { - mDXT1TextureSupport = false; - } - - if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC3_UNORM, &formatSupport))) - { - mDXT3TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; - } - else - { - mDXT3TextureSupport = false; - } - - if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC5_UNORM, &formatSupport))) - { - mDXT5TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; - } - else - { - mDXT5TextureSupport = false; - } - - // Check depth texture support - DXGI_FORMAT depthTextureFormats[] = - { - DXGI_FORMAT_D16_UNORM, - DXGI_FORMAT_D24_UNORM_S8_UINT, - }; - - static const unsigned int requiredDepthTextureFlags = D3D11_FORMAT_SUPPORT_DEPTH_STENCIL | - D3D11_FORMAT_SUPPORT_TEXTURE2D; - - mDepthTextureSupport = true; - for (unsigned int i = 0; i < ArraySize(depthTextureFormats); i++) - { - if (SUCCEEDED(mDevice->CheckFormatSupport(depthTextureFormats[i], &formatSupport))) - { - mDepthTextureSupport = mDepthTextureSupport && ((formatSupport & requiredDepthTextureFlags) == requiredDepthTextureFlags); - } - else - { - mDepthTextureSupport = false; - } - } - - return EGL_SUCCESS; -} - -// do any one-time device initialization -// NOTE: this is also needed after a device lost/reset -// to reset the scene status and ensure the default states are reset. -void Renderer11::initializeDevice() -{ - mStateCache.initialize(mDevice); - mInputLayoutCache.initialize(mDevice, mDeviceContext); - - ASSERT(!mVertexDataManager && !mIndexDataManager); - mVertexDataManager = new VertexDataManager(this); - mIndexDataManager = new IndexDataManager(this); - - markAllStateDirty(); -} - -int Renderer11::generateConfigs(ConfigDesc **configDescList) -{ - unsigned int numRenderFormats = ArraySize(RenderTargetFormats); - unsigned int numDepthFormats = ArraySize(DepthStencilFormats); - (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats]; - int numConfigs = 0; - - for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) - { - for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) - { - DXGI_FORMAT renderTargetFormat = RenderTargetFormats[formatIndex]; - - UINT formatSupport = 0; - HRESULT result = mDevice->CheckFormatSupport(renderTargetFormat, &formatSupport); - - if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) - { - DXGI_FORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex]; - - bool depthStencilFormatOK = true; - - if (depthStencilFormat != DXGI_FORMAT_UNKNOWN) - { - UINT formatSupport = 0; - result = mDevice->CheckFormatSupport(depthStencilFormat, &formatSupport); - depthStencilFormatOK = SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL); - } - - if (depthStencilFormatOK) - { - ConfigDesc newConfig; - newConfig.renderTargetFormat = d3d11_gl::ConvertBackBufferFormat(renderTargetFormat); - newConfig.depthStencilFormat = d3d11_gl::ConvertDepthStencilFormat(depthStencilFormat); - newConfig.multiSample = 0; // FIXME: enumerate multi-sampling - newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast - - (*configDescList)[numConfigs++] = newConfig; - } - } - } - } - - return numConfigs; -} - -void Renderer11::deleteConfigs(ConfigDesc *configDescList) -{ - delete [] (configDescList); -} - -void Renderer11::sync(bool block) -{ - if (block) - { - HRESULT result; - - if (!mSyncQuery) - { - D3D11_QUERY_DESC queryDesc; - queryDesc.Query = D3D11_QUERY_EVENT; - queryDesc.MiscFlags = 0; - - result = mDevice->CreateQuery(&queryDesc, &mSyncQuery); - ASSERT(SUCCEEDED(result)); - } - - mDeviceContext->End(mSyncQuery); - mDeviceContext->Flush(); - - do - { - result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); - - // Keep polling, but allow other threads to do something useful first - Sleep(0); - - if (testDeviceLost(true)) - { - return; - } - } - while (result == S_FALSE); - } - else - { - mDeviceContext->Flush(); - } -} - -SwapChain *Renderer11::createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) -{ - return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat); -} - -void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) -{ - if (type == gl::SAMPLER_PIXEL) - { - if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS) - { - ERR("Pixel shader sampler index %i is not valid.", index); - return; - } - - if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) - { - ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState); - - if (!dxSamplerState) - { - ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default" - "sampler state for pixel shaders at slot %i.", index); - } - - mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState); - - mCurPixelSamplerStates[index] = samplerState; - } - - mForceSetPixelSamplerStates[index] = false; - } - else if (type == gl::SAMPLER_VERTEX) - { - if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) - { - ERR("Vertex shader sampler index %i is not valid.", index); - return; - } - - if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) - { - ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState); - - if (!dxSamplerState) - { - ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default" - "sampler state for vertex shaders at slot %i.", index); - } - - mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState); - - mCurVertexSamplerStates[index] = samplerState; - } - - mForceSetVertexSamplerStates[index] = false; - } - else UNREACHABLE(); -} - -void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture) -{ - ID3D11ShaderResourceView *textureSRV = NULL; - unsigned int serial = 0; - bool forceSetTexture = false; - - if (texture) - { - TextureStorageInterface *texStorage = texture->getNativeTexture(); - if (texStorage) - { - TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance()); - textureSRV = storage11->getSRV(); - } - - // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly - // missing the shader resource view - ASSERT(textureSRV != NULL); - - serial = texture->getTextureSerial(); - forceSetTexture = texture->hasDirtyImages(); - } - - if (type == gl::SAMPLER_PIXEL) - { - if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS) - { - ERR("Pixel shader sampler index %i is not valid.", index); - return; - } - - if (forceSetTexture || mCurPixelTextureSerials[index] != serial) - { - mDeviceContext->PSSetShaderResources(index, 1, &textureSRV); - } - - mCurPixelTextureSerials[index] = serial; - } - else if (type == gl::SAMPLER_VERTEX) - { - if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) - { - ERR("Vertex shader sampler index %i is not valid.", index); - return; - } - - if (forceSetTexture || mCurVertexTextureSerials[index] != serial) - { - mDeviceContext->VSSetShaderResources(index, 1, &textureSRV); - } - - mCurVertexTextureSerials[index] = serial; - } - else UNREACHABLE(); -} - -void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) -{ - if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0) - { - ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mScissorEnabled, - mCurDepthSize); - if (!dxRasterState) - { - ERR("NULL rasterizer state returned by RenderStateCache::getRasterizerState, setting the default" - "rasterizer state."); - } - - mDeviceContext->RSSetState(dxRasterState); - - mCurRasterState = rasterState; - } - - mForceSetRasterState = false; -} - -void Renderer11::setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, - unsigned int sampleMask) -{ - if (mForceSetBlendState || - memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 || - memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0 || - sampleMask != mCurSampleMask) - { - ID3D11BlendState *dxBlendState = mStateCache.getBlendState(blendState); - if (!dxBlendState) - { - ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default " - "blend state."); - } - - float blendColors[4] = {0.0f}; - if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && - blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) - { - blendColors[0] = blendColor.red; - blendColors[1] = blendColor.green; - blendColors[2] = blendColor.blue; - blendColors[3] = blendColor.alpha; - } - else - { - blendColors[0] = blendColor.alpha; - blendColors[1] = blendColor.alpha; - blendColors[2] = blendColor.alpha; - blendColors[3] = blendColor.alpha; - } - - mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask); - - mCurBlendState = blendState; - mCurBlendColor = blendColor; - mCurSampleMask = sampleMask; - } - - mForceSetBlendState = false; -} - -void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW) -{ - if (mForceSetDepthStencilState || - memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 || - stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef) - { - if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || - stencilRef != stencilBackRef || - depthStencilState.stencilMask != depthStencilState.stencilBackMask) - { - ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are " - "invalid under WebGL."); - return gl::error(GL_INVALID_OPERATION); - } - - ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState); - if (!dxDepthStencilState) - { - ERR("NULL depth stencil state returned by RenderStateCache::getDepthStencilState, " - "setting the default depth stencil state."); - } - - mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, static_cast(stencilRef)); - - mCurDepthStencilState = depthStencilState; - mCurStencilRef = stencilRef; - mCurStencilBackRef = stencilBackRef; - } - - mForceSetDepthStencilState = false; -} - -void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) -{ - if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || - enabled != mScissorEnabled) - { - if (enabled) - { - D3D11_RECT rect; - rect.left = std::max(0, scissor.x); - rect.top = std::max(0, scissor.y); - rect.right = scissor.x + std::max(0, scissor.width); - rect.bottom = scissor.y + std::max(0, scissor.height); - - mDeviceContext->RSSetScissorRects(1, &rect); - } - - if (enabled != mScissorEnabled) - { - mForceSetRasterState = true; - } - - mCurScissor = scissor; - mScissorEnabled = enabled; - } - - mForceSetScissor = false; -} - -bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport) -{ - gl::Rectangle actualViewport = viewport; - float actualZNear = gl::clamp01(zNear); - float actualZFar = gl::clamp01(zFar); - if (ignoreViewport) - { - actualViewport.x = 0; - actualViewport.y = 0; - actualViewport.width = mRenderTargetDesc.width; - actualViewport.height = mRenderTargetDesc.height; - actualZNear = 0.0f; - actualZFar = 1.0f; - } - - // Get D3D viewport bounds, which depends on the feature level - const Range& viewportBounds = getViewportBounds(); - - // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds - D3D11_VIEWPORT dxViewport; - dxViewport.TopLeftX = gl::clamp(actualViewport.x, viewportBounds.start, viewportBounds.end); - dxViewport.TopLeftY = gl::clamp(actualViewport.y, viewportBounds.start, viewportBounds.end); - dxViewport.Width = gl::clamp(actualViewport.width, 0, getMaxViewportDimension()); - dxViewport.Height = gl::clamp(actualViewport.height, 0, getMaxViewportDimension()); - dxViewport.Width = std::min((int)dxViewport.Width, viewportBounds.end - static_cast(dxViewport.TopLeftX)); - dxViewport.Height = std::min((int)dxViewport.Height, viewportBounds.end - static_cast(dxViewport.TopLeftY)); - dxViewport.MinDepth = actualZNear; - dxViewport.MaxDepth = actualZFar; - - if (dxViewport.Width <= 0 || dxViewport.Height <= 0) - { - return false; // Nothing to render - } - - bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || - actualZNear != mCurNear || actualZFar != mCurFar; - - if (viewportChanged) - { - mDeviceContext->RSSetViewports(1, &dxViewport); - - mCurViewport = actualViewport; - mCurNear = actualZNear; - mCurFar = actualZFar; - - mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f; - mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f; - mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); - mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); - - mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f; - mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f; - - mVertexConstants.depthRange[0] = actualZNear; - mVertexConstants.depthRange[1] = actualZFar; - mVertexConstants.depthRange[2] = actualZFar - actualZNear; - - mPixelConstants.depthRange[0] = actualZNear; - mPixelConstants.depthRange[1] = actualZFar; - mPixelConstants.depthRange[2] = actualZFar - actualZNear; - } - - mForceSetViewport = false; - return true; -} - -bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) -{ - D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; - - GLsizei minCount = 0; - - switch (mode) - { - case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; minCount = 1; break; - case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; minCount = 2; break; - case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; - case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; - case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; - case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; minCount = 3; break; - // emulate fans via rewriting index buffer - case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; - default: - return gl::error(GL_INVALID_ENUM, false); - } - - if (primitiveTopology != mCurrentPrimitiveTopology) - { - mDeviceContext->IASetPrimitiveTopology(primitiveTopology); - mCurrentPrimitiveTopology = primitiveTopology; - } - - return count >= minCount; -} - -bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) -{ - // Get the color render buffer and serial - // Also extract the render target dimensions and view - unsigned int renderTargetWidth = 0; - unsigned int renderTargetHeight = 0; - GLenum renderTargetFormat = 0; - unsigned int renderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {0}; - ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; - bool missingColorRenderTarget = true; - - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - const GLenum drawBufferState = framebuffer->getDrawBufferState(colorAttachment); - - if (framebuffer->getColorbufferType(colorAttachment) != GL_NONE && drawBufferState != GL_NONE) - { - // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order) - ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment)); - - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(colorAttachment); - - if (!colorbuffer) - { - ERR("render target pointer unexpectedly null."); - return false; - } - - // check for zero-sized default framebuffer, which is a special case. - // in this case we do not wish to modify any state and just silently return false. - // this will not report any gl error but will cause the calling method to return. - if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) - { - return false; - } - - renderTargetSerials[colorAttachment] = colorbuffer->getSerial(); - - // Extract the render target dimensions and view - RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); - if (!renderTarget) - { - ERR("render target pointer unexpectedly null."); - return false; - } - - framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView(); - if (!framebufferRTVs[colorAttachment]) - { - ERR("render target view pointer unexpectedly null."); - return false; - } - - if (missingColorRenderTarget) - { - renderTargetWidth = colorbuffer->getWidth(); - renderTargetHeight = colorbuffer->getHeight(); - renderTargetFormat = colorbuffer->getActualFormat(); - missingColorRenderTarget = false; - } - } - } - - // Get the depth stencil render buffer and serials - gl::Renderbuffer *depthStencil = NULL; - unsigned int depthbufferSerial = 0; - unsigned int stencilbufferSerial = 0; - if (framebuffer->getDepthbufferType() != GL_NONE) - { - depthStencil = framebuffer->getDepthbuffer(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - SafeRelease(framebufferRTVs); - return false; - } - - depthbufferSerial = depthStencil->getSerial(); - } - else if (framebuffer->getStencilbufferType() != GL_NONE) - { - depthStencil = framebuffer->getStencilbuffer(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - SafeRelease(framebufferRTVs); - return false; - } - - stencilbufferSerial = depthStencil->getSerial(); - } - - // Extract the depth stencil sizes and view - unsigned int depthSize = 0; - unsigned int stencilSize = 0; - ID3D11DepthStencilView* framebufferDSV = NULL; - if (depthStencil) - { - RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getDepthStencil()); - if (!depthStencilRenderTarget) - { - ERR("render target pointer unexpectedly null."); - SafeRelease(framebufferRTVs); - return false; - } - - framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); - if (!framebufferDSV) - { - ERR("depth stencil view pointer unexpectedly null."); - SafeRelease(framebufferRTVs); - return false; - } - - // If there is no render buffer, the width, height and format values come from - // the depth stencil - if (missingColorRenderTarget) - { - renderTargetWidth = depthStencil->getWidth(); - renderTargetHeight = depthStencil->getHeight(); - renderTargetFormat = depthStencil->getActualFormat(); - } - - depthSize = depthStencil->getDepthSize(); - stencilSize = depthStencil->getStencilSize(); - } - - // Apply the render target and depth stencil - if (!mRenderTargetDescInitialized || !mDepthStencilInitialized || - memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 || - depthbufferSerial != mAppliedDepthbufferSerial || - stencilbufferSerial != mAppliedStencilbufferSerial) - { - mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), framebufferRTVs, framebufferDSV); - - mRenderTargetDesc.width = renderTargetWidth; - mRenderTargetDesc.height = renderTargetHeight; - mRenderTargetDesc.format = renderTargetFormat; - mForceSetViewport = true; - mForceSetScissor = true; - - if (!mDepthStencilInitialized || depthSize != mCurDepthSize) - { - mCurDepthSize = depthSize; - mForceSetRasterState = true; - } - - mCurStencilSize = stencilSize; - - for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) - { - mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex]; - } - mAppliedDepthbufferSerial = depthbufferSerial; - mAppliedStencilbufferSerial = stencilbufferSerial; - mRenderTargetDescInitialized = true; - mDepthStencilInitialized = true; - } - - return true; -} - -GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) -{ - TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; - GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances); - if (err != GL_NO_ERROR) - { - return err; - } - - return mInputLayoutCache.applyVertexBuffers(attributes, programBinary); -} - -GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) -{ - GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); - - if (err == GL_NO_ERROR) - { - if (indexInfo->storage) - { - if (indexInfo->serial != mAppliedStorageIBSerial || indexInfo->startOffset != mAppliedIBOffset) - { - BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage); - IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); - - mDeviceContext->IASetIndexBuffer(storage->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset); - - mAppliedIBSerial = 0; - mAppliedStorageIBSerial = storage->getSerial(); - mAppliedIBOffset = indexInfo->startOffset; - } - } - else if (indexInfo->serial != mAppliedIBSerial || indexInfo->startOffset != mAppliedIBOffset) - { - IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); - - mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset); - - mAppliedIBSerial = indexInfo->serial; - mAppliedStorageIBSerial = 0; - mAppliedIBOffset = indexInfo->startOffset; - } - } - - return err; -} - -void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances) -{ - if (mode == GL_LINE_LOOP) - { - drawLineLoop(count, GL_NONE, NULL, 0, NULL); - } - else if (mode == GL_TRIANGLE_FAN) - { - drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances); - } - else if (instances > 0) - { - mDeviceContext->DrawInstanced(count, instances, 0, 0); - } - else - { - mDeviceContext->Draw(count, 0); - } -} - -void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) -{ - if (mode == GL_LINE_LOOP) - { - drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer); - } - else if (mode == GL_TRIANGLE_FAN) - { - drawTriangleFan(count, type, indices, indexInfo.minIndex, elementArrayBuffer, instances); - } - else if (instances > 0) - { - mDeviceContext->DrawIndexedInstanced(count, instances, 0, -static_cast(indexInfo.minIndex), 0); - } - else - { - mDeviceContext->DrawIndexed(count, 0, -static_cast(indexInfo.minIndex)); - } -} - -template -static void drawLineLoopIndexed(T *data, GLenum type, const GLvoid *indices, GLsizei count) -{ - switch (type) - { - case GL_NONE: // Non-indexed draw - for (int i = 0; i < count; i++) - { - data[i] = i; - } - data[count] = 0; - break; - case GL_UNSIGNED_BYTE: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_SHORT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_INT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - default: UNREACHABLE(); - } -} - -void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) -{ - // Get the raw indices for an indexed draw - if (type != GL_NONE && elementArrayBuffer) - { - gl::Buffer *indexBuffer = elementArrayBuffer; - BufferStorage *storage = indexBuffer->getStorage(); - intptr_t offset = reinterpret_cast(indices); - indices = static_cast(storage->getData()) + offset; - } - - if (!mLineLoopIB) - { - mLineLoopIB = new StreamingIndexBufferInterface(this); - if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) - { - delete mLineLoopIB; - mLineLoopIB = NULL; - - ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - } - - // Checked by Renderer11::applyPrimitiveType - ASSERT(count >= 0); - - if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned int))) - { - ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); - return gl::error(GL_OUT_OF_MEMORY); - } - - const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned int); - if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) - { - ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - - void* mappedMemory = NULL; - unsigned int offset; - if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) - { - ERR("Could not map index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - - if (get32BitIndexSupport()) - drawLineLoopIndexed(reinterpret_cast(mappedMemory), type, indices, count); - else - drawLineLoopIndexed(reinterpret_cast(mappedMemory), type, indices, count); - - unsigned int indexBufferOffset = offset; - - if (!mLineLoopIB->unmapBuffer()) - { - ERR("Could not unmap index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - - if (mAppliedIBSerial != mLineLoopIB->getSerial() || mAppliedIBOffset != indexBufferOffset) - { - IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer()); - - mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); - mAppliedIBSerial = mLineLoopIB->getSerial(); - mAppliedStorageIBSerial = 0; - mAppliedIBOffset = indexBufferOffset; - } - - mDeviceContext->DrawIndexed(count + 1, 0, -minIndex); -} - -template -static void drawTriangleFanIndexed(T *data, GLenum type, const GLvoid *indices, unsigned int numTris) -{ - switch (type) - { - case GL_NONE: // Non-indexed draw - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = 0; - data[i*3 + 1] = i + 1; - data[i*3 + 2] = i + 2; - } - break; - case GL_UNSIGNED_BYTE: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - case GL_UNSIGNED_SHORT: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - case GL_UNSIGNED_INT: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - default: UNREACHABLE(); - } -} - -void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances) -{ - // Get the raw indices for an indexed draw - if (type != GL_NONE && elementArrayBuffer) - { - gl::Buffer *indexBuffer = elementArrayBuffer; - BufferStorage *storage = indexBuffer->getStorage(); - intptr_t offset = reinterpret_cast(indices); - indices = static_cast(storage->getData()) + offset; - } - - if (!mTriangleFanIB) - { - mTriangleFanIB = new StreamingIndexBufferInterface(this); - if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) - { - delete mTriangleFanIB; - mTriangleFanIB = NULL; - - ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN."); - return gl::error(GL_OUT_OF_MEMORY); - } - } - - // Checked by Renderer11::applyPrimitiveType - ASSERT(count >= 3); - - const unsigned int numTris = count - 2; - - if (numTris > (std::numeric_limits::max() / (sizeof(unsigned int) * 3))) - { - ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required."); - return gl::error(GL_OUT_OF_MEMORY); - } - - const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int); - if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) - { - ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN."); - return gl::error(GL_OUT_OF_MEMORY); - } - - void* mappedMemory = NULL; - unsigned int offset; - if (!mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) - { - ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN."); - return gl::error(GL_OUT_OF_MEMORY); - } - - if (get32BitIndexSupport()) - drawTriangleFanIndexed(reinterpret_cast(mappedMemory), type, indices, numTris); - else - drawTriangleFanIndexed(reinterpret_cast(mappedMemory), type, indices, numTris); - - unsigned int indexBufferOffset = offset; - - if (!mTriangleFanIB->unmapBuffer()) - { - ERR("Could not unmap scratch index buffer for GL_TRIANGLE_FAN."); - return gl::error(GL_OUT_OF_MEMORY); - } - - if (mAppliedIBSerial != mTriangleFanIB->getSerial() || mAppliedIBOffset != indexBufferOffset) - { - IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer()); - - mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); - mAppliedIBSerial = mTriangleFanIB->getSerial(); - mAppliedStorageIBSerial = 0; - mAppliedIBOffset = indexBufferOffset; - } - - if (instances > 0) - { - mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0); - } - else - { - mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex); - } -} - -void Renderer11::applyShaders(gl::ProgramBinary *programBinary) -{ - unsigned int programBinarySerial = programBinary->getSerial(); - const bool updateProgramState = (programBinarySerial != mAppliedProgramBinarySerial); - - if (updateProgramState) - { - ShaderExecutable *vertexExe = programBinary->getVertexExecutable(); - ShaderExecutable *pixelExe = programBinary->getPixelExecutable(); - - ID3D11VertexShader *vertexShader = NULL; - if (vertexExe) vertexShader = ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader(); - - ID3D11PixelShader *pixelShader = NULL; - if (pixelExe) pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader(); - - mDeviceContext->PSSetShader(pixelShader, NULL, 0); - mDeviceContext->VSSetShader(vertexShader, NULL, 0); - - programBinary->dirtyAllUniforms(); - - mAppliedProgramBinarySerial = programBinarySerial; - } - - // Only use the geometry shader currently for point sprite drawing - const bool usesGeometryShader = (programBinary->usesGeometryShader() && mCurRasterState.pointDrawMode); - - if (updateProgramState || usesGeometryShader != mIsGeometryShaderActive) - { - if (usesGeometryShader) - { - ShaderExecutable *geometryExe = programBinary->getGeometryExecutable(); - ID3D11GeometryShader *geometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader(); - mDeviceContext->GSSetShader(geometryShader, NULL, 0); - } - else - { - mDeviceContext->GSSetShader(NULL, NULL, 0); - } - - mIsGeometryShaderActive = usesGeometryShader; - } -} - -void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) -{ - ShaderExecutable11 *vertexExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable()); - ShaderExecutable11 *pixelExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getPixelExecutable()); - - unsigned int totalRegisterCountVS = 0; - unsigned int totalRegisterCountPS = 0; - - bool vertexUniformsDirty = false; - bool pixelUniformsDirty = false; - - for (gl::UniformArray::const_iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++) - { - const gl::Uniform *uniform = *uniform_iterator; - - if (uniform->vsRegisterIndex >= 0) - { - totalRegisterCountVS += uniform->registerCount; - vertexUniformsDirty = vertexUniformsDirty || uniform->dirty; - } - - if (uniform->psRegisterIndex >= 0) - { - totalRegisterCountPS += uniform->registerCount; - pixelUniformsDirty = pixelUniformsDirty || uniform->dirty; - } - } - - ID3D11Buffer *vertexConstantBuffer = vertexExecutable->getConstantBuffer(mDevice, totalRegisterCountVS); - ID3D11Buffer *pixelConstantBuffer = pixelExecutable->getConstantBuffer(mDevice, totalRegisterCountPS); - - float (*mapVS)[4] = NULL; - float (*mapPS)[4] = NULL; - - if (totalRegisterCountVS > 0 && vertexUniformsDirty) - { - D3D11_MAPPED_SUBRESOURCE map = {0}; - HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); - ASSERT(SUCCEEDED(result)); - mapVS = (float(*)[4])map.pData; - } - - if (totalRegisterCountPS > 0 && pixelUniformsDirty) - { - D3D11_MAPPED_SUBRESOURCE map = {0}; - HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); - ASSERT(SUCCEEDED(result)); - mapPS = (float(*)[4])map.pData; - } - - for (gl::UniformArray::iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++) - { - gl::Uniform *uniform = *uniform_iterator; - - if (uniform->type != GL_SAMPLER_2D && uniform->type != GL_SAMPLER_CUBE) - { - if (uniform->vsRegisterIndex >= 0 && mapVS) - { - memcpy(mapVS + uniform->vsRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4])); - } - - if (uniform->psRegisterIndex >= 0 && mapPS) - { - memcpy(mapPS + uniform->psRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4])); - } - } - - uniform->dirty = false; - } - - if (mapVS) - { - mDeviceContext->Unmap(vertexConstantBuffer, 0); - } - - if (mapPS) - { - mDeviceContext->Unmap(pixelConstantBuffer, 0); - } - - if (mCurrentVertexConstantBuffer != vertexConstantBuffer) - { - mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer); - mCurrentVertexConstantBuffer = vertexConstantBuffer; - } - - if (mCurrentPixelConstantBuffer != pixelConstantBuffer) - { - mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer); - mCurrentPixelConstantBuffer = pixelConstantBuffer; - } - - // Driver uniforms - if (!mDriverConstantBufferVS) - { - D3D11_BUFFER_DESC constantBufferDescription = {0}; - constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants); - constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; - constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - constantBufferDescription.CPUAccessFlags = 0; - constantBufferDescription.MiscFlags = 0; - constantBufferDescription.StructureByteStride = 0; - - HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS); - ASSERT(SUCCEEDED(result)); - - mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS); - } - - if (!mDriverConstantBufferPS) - { - D3D11_BUFFER_DESC constantBufferDescription = {0}; - constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants); - constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; - constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - constantBufferDescription.CPUAccessFlags = 0; - constantBufferDescription.MiscFlags = 0; - constantBufferDescription.StructureByteStride = 0; - - HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS); - ASSERT(SUCCEEDED(result)); - - mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS); - } - - if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0) - { - mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0); - memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants)); - } - - if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0) - { - mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0); - memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants)); - } - - // needed for the point sprite geometry shader - if (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0 && mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) - { - mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); - mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; - } -} - -void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) -{ - bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha; - bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) && - !(clearParams.colorMaskRed && clearParams.colorMaskGreen && - clearParams.colorMaskBlue && alphaUnmasked); - - unsigned int stencilUnmasked = 0x0; - if (frameBuffer->hasStencil()) - { - unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat()); - stencilUnmasked = (0x1 << stencilSize) - 1; - } - bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) && - (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; - - bool needScissoredClear = mScissorEnabled && (mCurScissor.x > 0 || mCurScissor.y > 0 || - mCurScissor.x + mCurScissor.width < mRenderTargetDesc.width || - mCurScissor.y + mCurScissor.height < mRenderTargetDesc.height); - - if (needMaskedColorClear || needMaskedStencilClear || needScissoredClear) - { - maskedClear(clearParams, frameBuffer->usingExtendedDrawBuffers()); - } - else - { - if (clearParams.mask & GL_COLOR_BUFFER_BIT) - { - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - if (frameBuffer->isEnabledColorAttachment(colorAttachment)) - { - gl::Renderbuffer *renderbufferObject = frameBuffer->getColorbuffer(colorAttachment); - if (renderbufferObject) - { - RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget()); - if (!renderTarget) - { - ERR("render target pointer unexpectedly null."); - return; - } - - ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); - if (!framebufferRTV) - { - ERR("render target view pointer unexpectedly null."); - return; - } - - const float clearValues[4] = { clearParams.colorClearValue.red, - clearParams.colorClearValue.green, - clearParams.colorClearValue.blue, - clearParams.colorClearValue.alpha }; - mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues); - } - } - } - } - if (clearParams.mask & GL_DEPTH_BUFFER_BIT || clearParams.mask & GL_STENCIL_BUFFER_BIT) - { - gl::Renderbuffer *renderbufferObject = frameBuffer->getDepthOrStencilbuffer(); - if (renderbufferObject) - { - RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getDepthStencil()); - if (!renderTarget) - { - ERR("render target pointer unexpectedly null."); - return; - } - - ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); - if (!framebufferDSV) - { - ERR("depth stencil view pointer unexpectedly null."); - return; - } - - UINT clearFlags = 0; - if (clearParams.mask & GL_DEPTH_BUFFER_BIT) - { - clearFlags |= D3D11_CLEAR_DEPTH; - } - if (clearParams.mask & GL_STENCIL_BUFFER_BIT) - { - clearFlags |= D3D11_CLEAR_STENCIL; - } - - float depthClear = gl::clamp01(clearParams.depthClearValue); - UINT8 stencilClear = clearParams.stencilClearValue & 0x000000FF; - - mDeviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); - } - } - } -} - -void Renderer11::maskedClear(const gl::ClearParameters &clearParams, bool usingExtendedDrawBuffers) -{ - HRESULT result; - - if (!mClearResourcesInitialized) - { - ASSERT(!mClearVB && !mClearVS && !mClearSinglePS && !mClearMultiplePS && !mClearScissorRS && !mClearNoScissorRS); - - D3D11_BUFFER_DESC vbDesc; - vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex) * 4; - vbDesc.Usage = D3D11_USAGE_DYNAMIC; - vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - vbDesc.MiscFlags = 0; - vbDesc.StructureByteStride = 0; - - result = mDevice->CreateBuffer(&vbDesc, NULL, &mClearVB); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearVB, "Renderer11 masked clear vertex buffer"); - - D3D11_INPUT_ELEMENT_DESC quadLayout[] = - { - { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - - result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Clear, sizeof(g_VS_Clear), &mClearIL); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearIL, "Renderer11 masked clear input layout"); - - result = mDevice->CreateVertexShader(g_VS_Clear, sizeof(g_VS_Clear), NULL, &mClearVS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearVS, "Renderer11 masked clear vertex shader"); - - result = mDevice->CreatePixelShader(g_PS_ClearSingle, sizeof(g_PS_ClearSingle), NULL, &mClearSinglePS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearSinglePS, "Renderer11 masked clear pixel shader (1 RT)"); - - result = mDevice->CreatePixelShader(g_PS_ClearMultiple, sizeof(g_PS_ClearMultiple), NULL, &mClearMultiplePS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearMultiplePS, "Renderer11 masked clear pixel shader (MRT)"); - - D3D11_RASTERIZER_DESC rsScissorDesc; - rsScissorDesc.FillMode = D3D11_FILL_SOLID; - rsScissorDesc.CullMode = D3D11_CULL_NONE; - rsScissorDesc.FrontCounterClockwise = FALSE; - rsScissorDesc.DepthBias = 0; - rsScissorDesc.DepthBiasClamp = 0.0f; - rsScissorDesc.SlopeScaledDepthBias = 0.0f; - rsScissorDesc.DepthClipEnable = FALSE; - rsScissorDesc.ScissorEnable = TRUE; - rsScissorDesc.MultisampleEnable = FALSE; - rsScissorDesc.AntialiasedLineEnable = FALSE; - - result = mDevice->CreateRasterizerState(&rsScissorDesc, &mClearScissorRS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearScissorRS, "Renderer11 masked clear scissor rasterizer state"); - - D3D11_RASTERIZER_DESC rsNoScissorDesc; - rsNoScissorDesc.FillMode = D3D11_FILL_SOLID; - rsNoScissorDesc.CullMode = D3D11_CULL_NONE; - rsNoScissorDesc.FrontCounterClockwise = FALSE; - rsNoScissorDesc.DepthBias = 0; - rsNoScissorDesc.DepthBiasClamp = 0.0f; - rsNoScissorDesc.SlopeScaledDepthBias = 0.0f; - rsNoScissorDesc.DepthClipEnable = FALSE; - rsNoScissorDesc.ScissorEnable = FALSE; - rsNoScissorDesc.MultisampleEnable = FALSE; - rsNoScissorDesc.AntialiasedLineEnable = FALSE; - - result = mDevice->CreateRasterizerState(&rsNoScissorDesc, &mClearNoScissorRS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearNoScissorRS, "Renderer11 masked clear no scissor rasterizer state"); - - mClearResourcesInitialized = true; - } - - // Prepare the depth stencil state to write depth values if the depth should be cleared - // and stencil values if the stencil should be cleared - gl::DepthStencilState glDSState; - glDSState.depthTest = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0; - glDSState.depthFunc = GL_ALWAYS; - glDSState.depthMask = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0; - glDSState.stencilTest = (clearParams.mask & GL_STENCIL_BUFFER_BIT) != 0; - glDSState.stencilFunc = GL_ALWAYS; - glDSState.stencilMask = 0; - glDSState.stencilFail = GL_REPLACE; - glDSState.stencilPassDepthFail = GL_REPLACE; - glDSState.stencilPassDepthPass = GL_REPLACE; - glDSState.stencilWritemask = clearParams.stencilWriteMask; - glDSState.stencilBackFunc = GL_ALWAYS; - glDSState.stencilBackMask = 0; - glDSState.stencilBackFail = GL_REPLACE; - glDSState.stencilBackPassDepthFail = GL_REPLACE; - glDSState.stencilBackPassDepthPass = GL_REPLACE; - glDSState.stencilBackWritemask = clearParams.stencilWriteMask; - - int stencilClear = clearParams.stencilClearValue & 0x000000FF; - - ID3D11DepthStencilState *dsState = mStateCache.getDepthStencilState(glDSState); - - // Prepare the blend state to use a write mask if the color buffer should be cleared - gl::BlendState glBlendState; - glBlendState.blend = false; - glBlendState.sourceBlendRGB = GL_ONE; - glBlendState.destBlendRGB = GL_ZERO; - glBlendState.sourceBlendAlpha = GL_ONE; - glBlendState.destBlendAlpha = GL_ZERO; - glBlendState.blendEquationRGB = GL_FUNC_ADD; - glBlendState.blendEquationAlpha = GL_FUNC_ADD; - glBlendState.colorMaskRed = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskRed : false; - glBlendState.colorMaskGreen = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskGreen : false; - glBlendState.colorMaskBlue = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskBlue : false; - glBlendState.colorMaskAlpha = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskAlpha : false; - glBlendState.sampleAlphaToCoverage = false; - glBlendState.dither = false; - - static const float blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; - static const UINT sampleMask = 0xFFFFFFFF; - - ID3D11BlendState *blendState = mStateCache.getBlendState(glBlendState); - - // Set the vertices - D3D11_MAPPED_SUBRESOURCE mappedResource; - result = mDeviceContext->Map(mClearVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Failed to map masked clear vertex buffer, HRESULT: 0x%X.", result); - return; - } - - d3d11::PositionDepthColorVertex *vertices = reinterpret_cast(mappedResource.pData); - - float depthClear = gl::clamp01(clearParams.depthClearValue); - d3d11::SetPositionDepthColorVertex(&vertices[0], -1.0f, 1.0f, depthClear, clearParams.colorClearValue); - d3d11::SetPositionDepthColorVertex(&vertices[1], -1.0f, -1.0f, depthClear, clearParams.colorClearValue); - d3d11::SetPositionDepthColorVertex(&vertices[2], 1.0f, 1.0f, depthClear, clearParams.colorClearValue); - d3d11::SetPositionDepthColorVertex(&vertices[3], 1.0f, -1.0f, depthClear, clearParams.colorClearValue); - - mDeviceContext->Unmap(mClearVB, 0); - - // Apply state - mDeviceContext->OMSetBlendState(blendState, blendFactors, sampleMask); - mDeviceContext->OMSetDepthStencilState(dsState, stencilClear); - mDeviceContext->RSSetState(mScissorEnabled ? mClearScissorRS : mClearNoScissorRS); - - // Apply shaders - ID3D11PixelShader *pixelShader = usingExtendedDrawBuffers ? mClearMultiplePS : mClearSinglePS; - - mDeviceContext->IASetInputLayout(mClearIL); - mDeviceContext->VSSetShader(mClearVS, NULL, 0); - mDeviceContext->PSSetShader(pixelShader, NULL, 0); - mDeviceContext->GSSetShader(NULL, NULL, 0); - - // Apply vertex buffer - static UINT stride = sizeof(d3d11::PositionDepthColorVertex); - static UINT startIdx = 0; - mDeviceContext->IASetVertexBuffers(0, 1, &mClearVB, &stride, &startIdx); - mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - - // Draw the clear quad - mDeviceContext->Draw(4, 0); - - // Clean up - markAllStateDirty(); -} - -void Renderer11::markAllStateDirty() -{ - for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) - { - mAppliedRenderTargetSerials[rtIndex] = 0; - } - mAppliedDepthbufferSerial = 0; - mAppliedStencilbufferSerial = 0; - mDepthStencilInitialized = false; - mRenderTargetDescInitialized = false; - - for (int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) - { - mForceSetVertexSamplerStates[i] = true; - mCurVertexTextureSerials[i] = 0; - } - for (int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++) - { - mForceSetPixelSamplerStates[i] = true; - mCurPixelTextureSerials[i] = 0; - } - - mForceSetBlendState = true; - mForceSetRasterState = true; - mForceSetDepthStencilState = true; - mForceSetScissor = true; - mForceSetViewport = true; - - mAppliedIBSerial = 0; - mAppliedStorageIBSerial = 0; - mAppliedIBOffset = 0; - - mAppliedProgramBinarySerial = 0; - memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants)); - memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants)); - - mInputLayoutCache.markDirty(); - - mCurrentVertexConstantBuffer = NULL; - mCurrentPixelConstantBuffer = NULL; - mCurrentGeometryConstantBuffer = NULL; - - mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; -} - -void Renderer11::releaseDeviceResources() -{ - mStateCache.clear(); - mInputLayoutCache.clear(); - - delete mVertexDataManager; - mVertexDataManager = NULL; - - delete mIndexDataManager; - mIndexDataManager = NULL; - - delete mLineLoopIB; - mLineLoopIB = NULL; - - delete mTriangleFanIB; - mTriangleFanIB = NULL; - - SafeRelease(mCopyVB); - SafeRelease(mCopySampler); - SafeRelease(mCopyIL); - SafeRelease(mCopyIL); - SafeRelease(mCopyVS); - SafeRelease(mCopyRGBAPS); - SafeRelease(mCopyRGBPS); - SafeRelease(mCopyLumPS); - SafeRelease(mCopyLumAlphaPS); - - mCopyResourcesInitialized = false; - - SafeRelease(mClearVB); - SafeRelease(mClearIL); - SafeRelease(mClearVS); - SafeRelease(mClearSinglePS); - SafeRelease(mClearMultiplePS); - SafeRelease(mClearScissorRS); - SafeRelease(mClearNoScissorRS); - - mClearResourcesInitialized = false; - - SafeRelease(mDriverConstantBufferVS); - SafeRelease(mDriverConstantBufferPS); - SafeRelease(mSyncQuery); -} - -void Renderer11::notifyDeviceLost() -{ - mDeviceLost = true; - mDisplay->notifyDeviceLost(); -} - -bool Renderer11::isDeviceLost() -{ - return mDeviceLost; -} - -// set notify to true to broadcast a message to all contexts of the device loss -bool Renderer11::testDeviceLost(bool notify) -{ - bool isLost = false; - - // GetRemovedReason is used to test if the device is removed - HRESULT result = mDevice->GetDeviceRemovedReason(); - isLost = d3d11::isDeviceLostError(result); - - if (isLost) - { - // Log error if this is a new device lost event - if (mDeviceLost == false) - { - ERR("The D3D11 device was removed: 0x%08X", result); - } - - // ensure we note the device loss -- - // we'll probably get this done again by notifyDeviceLost - // but best to remember it! - // Note that we don't want to clear the device loss status here - // -- this needs to be done by resetDevice - mDeviceLost = true; - if (notify) - { - notifyDeviceLost(); - } - } - - return isLost; -} - -bool Renderer11::testDeviceResettable() -{ - // determine if the device is resettable by creating a dummy device - PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); - - if (D3D11CreateDevice == NULL) - { - return false; - } - - D3D_FEATURE_LEVEL featureLevels[] = - { - D3D_FEATURE_LEVEL_11_1, - D3D_FEATURE_LEVEL_11_0, - D3D_FEATURE_LEVEL_10_1, - D3D_FEATURE_LEVEL_10_0, - D3D_FEATURE_LEVEL_9_3, - D3D_FEATURE_LEVEL_9_2, - D3D_FEATURE_LEVEL_9_1, - }; - - ID3D11Device* dummyDevice; - D3D_FEATURE_LEVEL dummyFeatureLevel; - ID3D11DeviceContext* dummyContext; - - HRESULT result = D3D11CreateDevice(NULL, - D3D_DRIVER_TYPE_HARDWARE, - NULL, - #if defined(_DEBUG) - D3D11_CREATE_DEVICE_DEBUG, - #else - 0, - #endif - featureLevels, - ArraySize(featureLevels), - D3D11_SDK_VERSION, - &dummyDevice, - &dummyFeatureLevel, - &dummyContext); - - if (!mDevice || FAILED(result)) - { - return false; - } - - dummyContext->Release(); - dummyDevice->Release(); - - return true; -} - -void Renderer11::release() -{ - releaseDeviceResources(); - - if (mDxgiFactory) - { - mDxgiFactory->Release(); - mDxgiFactory = NULL; - } - - if (mDxgiAdapter) - { - mDxgiAdapter->Release(); - mDxgiAdapter = NULL; - } - - if (mDeviceContext) - { - mDeviceContext->ClearState(); - mDeviceContext->Flush(); - mDeviceContext->Release(); - mDeviceContext = NULL; - } - - if (mDevice) - { - mDevice->Release(); - mDevice = NULL; - } - - if (mD3d11Module) - { - FreeLibrary(mD3d11Module); - mD3d11Module = NULL; - } - - if (mDxgiModule) - { - FreeLibrary(mDxgiModule); - mDxgiModule = NULL; - } -} - -bool Renderer11::resetDevice() -{ - // recreate everything - release(); - EGLint result = initialize(); - - if (result != EGL_SUCCESS) - { - ERR("Could not reinitialize D3D11 device: %08X", result); - return false; - } - - mDeviceLost = false; - - return true; -} - -DWORD Renderer11::getAdapterVendor() const -{ - return mAdapterDescription.VendorId; -} - -std::string Renderer11::getRendererDescription() const -{ - std::ostringstream rendererString; - - rendererString << mDescription; - rendererString << " Direct3D11"; - - rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel(); - rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel(); - - return rendererString.str(); -} - -GUID Renderer11::getAdapterIdentifier() const -{ - // Use the adapter LUID as our adapter ID - // This number is local to a machine is only guaranteed to be unique between restarts - META_ASSERT(sizeof(LUID) <= sizeof(GUID)); - GUID adapterId = {0}; - memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID)); - return adapterId; -} - -bool Renderer11::getBGRATextureSupport() const -{ - return mBGRATextureSupport; -} - -bool Renderer11::getDXT1TextureSupport() -{ - return mDXT1TextureSupport; -} - -bool Renderer11::getDXT3TextureSupport() -{ - return mDXT3TextureSupport; -} - -bool Renderer11::getDXT5TextureSupport() -{ - return mDXT5TextureSupport; -} - -bool Renderer11::getDepthTextureSupport() const -{ - return mDepthTextureSupport; -} - -bool Renderer11::getFloat32TextureSupport(bool *filtering, bool *renderable) -{ - *renderable = mFloat32RenderSupport; - *filtering = mFloat32FilterSupport; - return mFloat32TextureSupport; -} - -bool Renderer11::getFloat16TextureSupport(bool *filtering, bool *renderable) -{ - *renderable = mFloat16RenderSupport; - *filtering = mFloat16FilterSupport; - return mFloat16TextureSupport; -} - -bool Renderer11::getLuminanceTextureSupport() -{ - return false; -} - -bool Renderer11::getLuminanceAlphaTextureSupport() -{ - return false; -} - -bool Renderer11::getTextureFilterAnisotropySupport() const -{ - return true; -} - -float Renderer11::getTextureMaxAnisotropy() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - return D3D11_MAX_MAXANISOTROPY; - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return D3D10_MAX_MAXANISOTROPY; - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - return 16; - case D3D_FEATURE_LEVEL_9_1: - return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; - default: UNREACHABLE(); - return 0; - } -} - -bool Renderer11::getEventQuerySupport() -{ - return true; -} - -Range Renderer11::getViewportBounds() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - return Range(D3D11_VIEWPORT_BOUNDS_MIN, D3D11_VIEWPORT_BOUNDS_MAX); - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return Range(D3D10_VIEWPORT_BOUNDS_MIN, D3D10_VIEWPORT_BOUNDS_MAX); - case D3D_FEATURE_LEVEL_9_3: - return Range(D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION * -2, D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2); - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return Range(D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION * -2, D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2); - default: UNREACHABLE(); - return Range(0, 0); - } -} - -unsigned int Renderer11::getMaxVertexTextureImageUnits() const -{ - META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4; - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return 0; - default: UNREACHABLE(); - return 0; - } -} - -unsigned int Renderer11::getMaxCombinedTextureImageUnits() const -{ - return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits(); -} - -unsigned int Renderer11::getReservedVertexUniformVectors() const -{ - return 0; // Driver uniforms are stored in a separate constant buffer -} - -unsigned int Renderer11::getReservedFragmentUniformVectors() const -{ - return 0; // Driver uniforms are stored in a separate constant buffer -} - -unsigned int Renderer11::getMaxVertexUniformVectors() const -{ - META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return MAX_VERTEX_UNIFORM_VECTORS_D3D11; - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return MAX_VERTEX_UNIFORM_VECTORS_D3D9; - default: - UNIMPLEMENTED(); - return 0; - } -} - -unsigned int Renderer11::getMaxFragmentUniformVectors() const -{ - META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11; - case D3D_FEATURE_LEVEL_9_3: - return 221; - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return 29; - default: UNREACHABLE(); - return 0; - } -} - -unsigned int Renderer11::getMaxVaryingVectors() const -{ - META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT); - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - return D3D11_VS_OUTPUT_REGISTER_COUNT; - case D3D_FEATURE_LEVEL_10_1: - return D3D10_1_VS_OUTPUT_REGISTER_COUNT; - case D3D_FEATURE_LEVEL_10_0: - return D3D10_VS_OUTPUT_REGISTER_COUNT; - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return 8; - default: UNREACHABLE(); - return 0; - } -} - -bool Renderer11::getNonPower2TextureSupport() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return true; - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return false; - default: UNREACHABLE(); - return false; - } -} - -bool Renderer11::getOcclusionQuerySupport() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - return true; - case D3D_FEATURE_LEVEL_9_1: - return false; - default: UNREACHABLE(); - return false; - } -} - -bool Renderer11::getInstancingSupport() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - case D3D_FEATURE_LEVEL_9_3: - return true; - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return false; - default: UNREACHABLE(); - return false; - } -} - -bool Renderer11::getShareHandleSupport() const -{ - // We only currently support share handles with BGRA surfaces, because - // chrome needs BGRA. Once chrome fixes this, we should always support them. - // PIX doesn't seem to support using share handles, so disable them. - return getBGRATextureSupport() && !gl::perfActive(); -} - -bool Renderer11::getDerivativeInstructionSupport() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - case D3D_FEATURE_LEVEL_9_3: - return true; - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return false; - default: UNREACHABLE(); - return false; - } -} - -bool Renderer11::getPostSubBufferSupport() const -{ - // D3D11 does not support present with dirty rectangles until D3D11.1 and DXGI 1.2. - return false; -} - -int Renderer11::getMajorShaderModel() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5 - case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4 - case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4 - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 4; // SM4 level 9, but treat as 4 - default: UNREACHABLE(); return 0; - } -} - -int Renderer11::getMinorShaderModel() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0 - case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1 - case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0 - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; - default: UNREACHABLE(); return 0; - } -} - -float Renderer11::getMaxPointSize() const -{ - // choose a reasonable maximum. we enforce this in the shader. - // (nb: on a Radeon 2600xt, DX9 reports a 256 max point size) - return 1024.0f; -} - -int Renderer11::getMaxViewportDimension() const -{ - // Maximum viewport size must be at least as large as the largest render buffer (or larger). - // In our case return the maximum texture size, which is the maximum render buffer size. - META_ASSERT(D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D11_VIEWPORT_BOUNDS_MAX); - META_ASSERT(D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D10_VIEWPORT_BOUNDS_MAX); - - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 - case D3D_FEATURE_LEVEL_9_3: - return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 - default: UNREACHABLE(); - return 0; - } -} - -int Renderer11::getMaxTextureWidth() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 - case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 - default: UNREACHABLE(); return 0; - } -} - -int Renderer11::getMaxTextureHeight() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 - case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 - default: UNREACHABLE(); return 0; - } -} - -bool Renderer11::get32BitIndexSupport() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return false; - default: UNREACHABLE(); return false; - } -} - -int Renderer11::getMinSwapInterval() const -{ - return 0; -} - -int Renderer11::getMaxSwapInterval() const -{ - return 4; -} - -int Renderer11::getMaxSupportedSamples() const -{ - return mMaxSupportedSamples; -} - -int Renderer11::getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const -{ - if (requested == 0) - { - return 0; - } - - MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); - if (iter != mMultisampleSupportMap.end()) - { - const MultisampleSupportInfo& info = iter->second; - for (unsigned int i = requested - 1; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++) - { - if (info.qualityLevels[i] > 0) - { - return i + 1; - } - } - } - - return -1; -} - -unsigned int Renderer11::getMaxRenderTargets() const -{ - META_ASSERT(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); - META_ASSERT(D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); - META_ASSERT(D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); - META_ASSERT(D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); - - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8 - case D3D_FEATURE_LEVEL_9_3: - return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT; // 4 - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT; // 1 - default: - UNREACHABLE(); - return 1; - } -} - -bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) -{ - if (source && dest) - { - TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source->getStorageInstance()); - TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest->getStorageInstance()); - - mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture()); - return true; - } - - return false; -} - -bool Renderer11::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) -{ - if (source && dest) - { - TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source->getStorageInstance()); - TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest->getStorageInstance()); - - mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture()); - return true; - } - - return false; -} - -bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) -{ - gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); - if (!colorbuffer) - { - ERR("Failed to retrieve the color buffer from the frame buffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); - if (!sourceRenderTarget) - { - ERR("Failed to retrieve the render target from the frame buffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - if (!source) - { - ERR("Failed to retrieve the render target view from the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); - if (!storage11) - { - ERR("Failed to retrieve the texture storage from the destination."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(level)); - if (!destRenderTarget) - { - ERR("Failed to retrieve the render target from the destination storage."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); - if (!dest) - { - ERR("Failed to retrieve the render target view from the destination render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - gl::Rectangle destRect; - destRect.x = xoffset; - destRect.y = yoffset; - destRect.width = sourceRect.width; - destRect.height = sourceRect.height; - - bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), - dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat); - - return ret; -} - -bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) -{ - gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); - if (!colorbuffer) - { - ERR("Failed to retrieve the color buffer from the frame buffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); - if (!sourceRenderTarget) - { - ERR("Failed to retrieve the render target from the frame buffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - if (!source) - { - ERR("Failed to retrieve the render target view from the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); - if (!storage11) - { - ERR("Failed to retrieve the texture storage from the destination."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(target, level)); - if (!destRenderTarget) - { - ERR("Failed to retrieve the render target from the destination storage."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); - if (!dest) - { - ERR("Failed to retrieve the render target view from the destination render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - gl::Rectangle destRect; - destRect.x = xoffset; - destRect.y = yoffset; - destRect.width = sourceRect.width; - destRect.height = sourceRect.height; - - bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), - dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat); - - return ret; -} - -bool Renderer11::copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight, - ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat) -{ - HRESULT result; - - if (!mCopyResourcesInitialized) - { - ASSERT(!mCopyVB && !mCopySampler && !mCopyIL && !mCopyVS && !mCopyRGBAPS && !mCopyRGBPS && !mCopyLumPS && !mCopyLumAlphaPS); - - D3D11_BUFFER_DESC vbDesc; - vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; - vbDesc.Usage = D3D11_USAGE_DYNAMIC; - vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - vbDesc.MiscFlags = 0; - vbDesc.StructureByteStride = 0; - - result = mDevice->CreateBuffer(&vbDesc, NULL, &mCopyVB); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyVB, "Renderer11 copy texture vertex buffer"); - - D3D11_SAMPLER_DESC samplerDesc; - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.MipLODBias = 0.0f; - samplerDesc.MaxAnisotropy = 0; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; - samplerDesc.BorderColor[0] = 0.0f; - samplerDesc.BorderColor[1] = 0.0f; - samplerDesc.BorderColor[2] = 0.0f; - samplerDesc.BorderColor[3] = 0.0f; - samplerDesc.MinLOD = 0.0f; - samplerDesc.MaxLOD = 0.0f; - - result = mDevice->CreateSamplerState(&samplerDesc, &mCopySampler); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopySampler, "Renderer11 copy sampler"); - - D3D11_INPUT_ELEMENT_DESC quadLayout[] = - { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - - result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mCopyIL); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyIL, "Renderer11 copy texture input layout"); - - result = mDevice->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mCopyVS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyVS, "Renderer11 copy texture vertex shader"); - - result = mDevice->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mCopyRGBAPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyRGBAPS, "Renderer11 copy texture RGBA pixel shader"); - - result = mDevice->CreatePixelShader(g_PS_PassthroughRGB, sizeof(g_PS_PassthroughRGB), NULL, &mCopyRGBPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyRGBPS, "Renderer11 copy texture RGB pixel shader"); - - result = mDevice->CreatePixelShader(g_PS_PassthroughLum, sizeof(g_PS_PassthroughLum), NULL, &mCopyLumPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyLumPS, "Renderer11 copy texture luminance pixel shader"); - - result = mDevice->CreatePixelShader(g_PS_PassthroughLumAlpha, sizeof(g_PS_PassthroughLumAlpha), NULL, &mCopyLumAlphaPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyLumAlphaPS, "Renderer11 copy texture luminance alpha pixel shader"); - - mCopyResourcesInitialized = true; - } - - // Verify the source and destination area sizes - if (sourceArea.x < 0 || sourceArea.x + sourceArea.width > static_cast(sourceWidth) || - sourceArea.y < 0 || sourceArea.y + sourceArea.height > static_cast(sourceHeight) || - destArea.x < 0 || destArea.x + destArea.width > static_cast(destWidth) || - destArea.y < 0 || destArea.y + destArea.height > static_cast(destHeight)) - { - return gl::error(GL_INVALID_VALUE, false); - } - - // Set vertices - D3D11_MAPPED_SUBRESOURCE mappedResource; - result = mDeviceContext->Map(mCopyVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - d3d11::PositionTexCoordVertex *vertices = static_cast(mappedResource.pData); - - // Create a quad in homogeneous coordinates - float x1 = (destArea.x / float(destWidth)) * 2.0f - 1.0f; - float y1 = ((destHeight - destArea.y - destArea.height) / float(destHeight)) * 2.0f - 1.0f; - float x2 = ((destArea.x + destArea.width) / float(destWidth)) * 2.0f - 1.0f; - float y2 = ((destHeight - destArea.y) / float(destHeight)) * 2.0f - 1.0f; - - float u1 = sourceArea.x / float(sourceWidth); - float v1 = sourceArea.y / float(sourceHeight); - float u2 = (sourceArea.x + sourceArea.width) / float(sourceWidth); - float v2 = (sourceArea.y + sourceArea.height) / float(sourceHeight); - - d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2); - d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1); - d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2); - d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1); - - mDeviceContext->Unmap(mCopyVB, 0); - - static UINT stride = sizeof(d3d11::PositionTexCoordVertex); - static UINT startIdx = 0; - mDeviceContext->IASetVertexBuffers(0, 1, &mCopyVB, &stride, &startIdx); - - // Apply state - mDeviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); - mDeviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); - mDeviceContext->RSSetState(NULL); - - // Apply shaders - mDeviceContext->IASetInputLayout(mCopyIL); - mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - mDeviceContext->VSSetShader(mCopyVS, NULL, 0); - - ID3D11PixelShader *ps = NULL; - switch(destFormat) - { - case GL_RGBA: ps = mCopyRGBAPS; break; - case GL_RGB: ps = mCopyRGBPS; break; - case GL_ALPHA: ps = mCopyRGBAPS; break; - case GL_BGRA_EXT: ps = mCopyRGBAPS; break; - case GL_LUMINANCE: ps = mCopyLumPS; break; - case GL_LUMINANCE_ALPHA: ps = mCopyLumAlphaPS; break; - default: UNREACHABLE(); ps = NULL; break; - } - - mDeviceContext->PSSetShader(ps, NULL, 0); - mDeviceContext->GSSetShader(NULL, NULL, 0); - - // Unset the currently bound shader resource to avoid conflicts - static ID3D11ShaderResourceView *const nullSRV = NULL; - mDeviceContext->PSSetShaderResources(0, 1, &nullSRV); - - // Apply render target - setOneTimeRenderTarget(dest); - - // Set the viewport - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = destWidth; - viewport.Height = destHeight; - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - mDeviceContext->RSSetViewports(1, &viewport); - - // Apply textures - mDeviceContext->PSSetShaderResources(0, 1, &source); - mDeviceContext->PSSetSamplers(0, 1, &mCopySampler); - - // Draw the quad - mDeviceContext->Draw(4, 0); - - // Unbind textures and render targets and vertex buffer - mDeviceContext->PSSetShaderResources(0, 1, &nullSRV); - - unapplyRenderTargets(); - - UINT zero = 0; - ID3D11Buffer *const nullBuffer = NULL; - mDeviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); - - markAllStateDirty(); - - return true; -} - -void Renderer11::unapplyRenderTargets() -{ - setOneTimeRenderTarget(NULL); -} - -void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView) -{ - ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; - - rtvArray[0] = renderTargetView; - - mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), rtvArray, NULL); - - // Do not preserve the serial for this one-time-use render target - for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) - { - mAppliedRenderTargetSerials[rtIndex] = 0; - } -} - -RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth) -{ - SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); - RenderTarget11 *renderTarget = NULL; - - if (depth) - { - // Note: depth stencil may be NULL for 0 sized surfaces - renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(), - swapChain11->getDepthStencilTexture(), NULL, - swapChain11->getWidth(), swapChain11->getHeight()); - } - else - { - // Note: render target may be NULL for 0 sized surfaces - renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(), - swapChain11->getOffscreenTexture(), - swapChain11->getRenderTargetShaderResource(), - swapChain11->getWidth(), swapChain11->getHeight()); - } - return renderTarget; -} - -RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) -{ - RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples, depth); - return renderTarget; -} - -ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type) -{ - ShaderExecutable11 *executable = NULL; - - switch (type) - { - case rx::SHADER_VERTEX: - { - ID3D11VertexShader *vshader = NULL; - HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vshader); - ASSERT(SUCCEEDED(result)); - - if (vshader) - { - executable = new ShaderExecutable11(function, length, vshader); - } - } - break; - case rx::SHADER_PIXEL: - { - ID3D11PixelShader *pshader = NULL; - HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pshader); - ASSERT(SUCCEEDED(result)); - - if (pshader) - { - executable = new ShaderExecutable11(function, length, pshader); - } - } - break; - case rx::SHADER_GEOMETRY: - { - ID3D11GeometryShader *gshader = NULL; - HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &gshader); - ASSERT(SUCCEEDED(result)); - - if (gshader) - { - executable = new ShaderExecutable11(function, length, gshader); - } - } - break; - default: - UNREACHABLE(); - break; - } - - return executable; -} - -ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type) -{ - std::string profile; - - switch (type) - { - case rx::SHADER_VERTEX: - profile = "vs_4_0"; - break; - case rx::SHADER_PIXEL: - profile = "ps_4_0"; - break; - case rx::SHADER_GEOMETRY: - profile = "gs_4_0"; - break; - default: - UNREACHABLE(); - return NULL; - } - - if (mFeatureLevel == D3D_FEATURE_LEVEL_9_3) - profile += "_level_9_3"; - else if (mFeatureLevel == D3D_FEATURE_LEVEL_9_2 || mFeatureLevel == D3D_FEATURE_LEVEL_9_1) - profile += "_level_9_1"; - - ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile.c_str(), D3DCOMPILE_OPTIMIZATION_LEVEL0, false); - if (!binary) - return NULL; - - ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type); - binary->Release(); - - return executable; -} - -VertexBuffer *Renderer11::createVertexBuffer() -{ - return new VertexBuffer11(this); -} - -IndexBuffer *Renderer11::createIndexBuffer() -{ - return new IndexBuffer11(this); -} - -BufferStorage *Renderer11::createBufferStorage() -{ - return new BufferStorage11(this); -} - -QueryImpl *Renderer11::createQuery(GLenum type) -{ - return new Query11(this, type); -} - -FenceImpl *Renderer11::createFence() -{ - return new Fence11(this); -} - -bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource) -{ - ASSERT(colorbuffer != NULL); - - RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); - if (renderTarget) - { - *subresourceIndex = renderTarget->getSubresourceIndex(); - - ID3D11RenderTargetView *colorBufferRTV = renderTarget->getRenderTargetView(); - if (colorBufferRTV) - { - ID3D11Resource *textureResource = NULL; - colorBufferRTV->GetResource(&textureResource); - - if (textureResource) - { - HRESULT result = textureResource->QueryInterface(IID_ID3D11Texture2D, (void**)resource); - textureResource->Release(); - - if (SUCCEEDED(result)) - { - return true; - } - else - { - ERR("Failed to extract the ID3D11Texture2D from the render target resource, " - "HRESULT: 0x%X.", result); - } - } - } - } - - return false; -} - -bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - bool blitRenderTarget, bool blitDepthStencil) -{ - if (blitRenderTarget) - { - gl::Renderbuffer *readBuffer = readTarget->getReadColorbuffer(); - - if (!readBuffer) - { - ERR("Failed to retrieve the read buffer from the read framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RenderTarget *readRenderTarget = readBuffer->getRenderTarget(); - - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - if (drawTarget->isEnabledColorAttachment(colorAttachment)) - { - gl::Renderbuffer *drawBuffer = drawTarget->getColorbuffer(colorAttachment); - - if (!drawBuffer) - { - ERR("Failed to retrieve the draw buffer from the draw framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget(); - - if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, false)) - { - return false; - } - } - } - } - - if (blitDepthStencil) - { - gl::Renderbuffer *readBuffer = readTarget->getDepthOrStencilbuffer(); - gl::Renderbuffer *drawBuffer = drawTarget->getDepthOrStencilbuffer(); - - if (!readBuffer) - { - ERR("Failed to retrieve the read depth-stencil buffer from the read framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - if (!drawBuffer) - { - ERR("Failed to retrieve the draw depth-stencil buffer from the draw framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RenderTarget *readRenderTarget = readBuffer->getDepthStencil(); - RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil(); - - if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, true)) - { - return false; - } - } - - return true; -} - -void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) -{ - ID3D11Texture2D *colorBufferTexture = NULL; - unsigned int subresourceIndex = 0; - - gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); - - if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) - { - gl::Rectangle area; - area.x = x; - area.y = y; - area.width = width; - area.height = height; - - readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, - packReverseRowOrder, packAlignment, pixels); - - colorBufferTexture->Release(); - colorBufferTexture = NULL; - } -} - -Image *Renderer11::createImage() -{ - return new Image11(); -} - -void Renderer11::generateMipmap(Image *dest, Image *src) -{ - Image11 *dest11 = Image11::makeImage11(dest); - Image11 *src11 = Image11::makeImage11(src); - Image11::generateMipmap(dest11, src11); -} - -TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain) -{ - SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); - return new TextureStorage11_2D(this, swapChain11); -} - -TextureStorage *Renderer11::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) -{ - return new TextureStorage11_2D(this, levels, internalformat, usage, forceRenderable, width, height); -} - -TextureStorage *Renderer11::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) -{ - return new TextureStorage11_Cube(this, levels, internalformat, usage, forceRenderable, size); -} - -static inline unsigned int getFastPixelCopySize(DXGI_FORMAT sourceFormat, GLenum destFormat, GLenum destType) -{ - if (sourceFormat == DXGI_FORMAT_A8_UNORM && - destFormat == GL_ALPHA && - destType == GL_UNSIGNED_BYTE) - { - return 1; - } - else if (sourceFormat == DXGI_FORMAT_R8G8B8A8_UNORM && - destFormat == GL_RGBA && - destType == GL_UNSIGNED_BYTE) - { - return 4; - } - else if (sourceFormat == DXGI_FORMAT_B8G8R8A8_UNORM && - destFormat == GL_BGRA_EXT && - destType == GL_UNSIGNED_BYTE) - { - return 4; - } - else if (sourceFormat == DXGI_FORMAT_R16G16B16A16_FLOAT && - destFormat == GL_RGBA && - destType == GL_HALF_FLOAT_OES) - { - return 8; - } - else if (sourceFormat == DXGI_FORMAT_R32G32B32_FLOAT && - destFormat == GL_RGB && - destType == GL_FLOAT) - { - return 12; - } - else if (sourceFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && - destFormat == GL_RGBA && - destType == GL_FLOAT) - { - return 16; - } - else - { - return 0; - } -} - -static inline void readPixelColor(const unsigned char *data, DXGI_FORMAT format, unsigned int x, - unsigned int y, int inputPitch, gl::Color *outColor) -{ - switch (format) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - { - unsigned int rgba = *reinterpret_cast(data + 4 * x + y * inputPitch); - outColor->red = (rgba & 0x000000FF) * (1.0f / 0x000000FF); - outColor->green = (rgba & 0x0000FF00) * (1.0f / 0x0000FF00); - outColor->blue = (rgba & 0x00FF0000) * (1.0f / 0x00FF0000); - outColor->alpha = (rgba & 0xFF000000) * (1.0f / 0xFF000000); - } - break; - - case DXGI_FORMAT_A8_UNORM: - { - outColor->red = 0.0f; - outColor->green = 0.0f; - outColor->blue = 0.0f; - outColor->alpha = *(data + x + y * inputPitch) / 255.0f; - } - break; - - case DXGI_FORMAT_R32G32B32A32_FLOAT: - { - outColor->red = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 0); - outColor->green = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 1); - outColor->blue = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 2); - outColor->alpha = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 3); - } - break; - - case DXGI_FORMAT_R32G32B32_FLOAT: - { - outColor->red = *(reinterpret_cast(data + 12 * x + y * inputPitch) + 0); - outColor->green = *(reinterpret_cast(data + 12 * x + y * inputPitch) + 1); - outColor->blue = *(reinterpret_cast(data + 12 * x + y * inputPitch) + 2); - outColor->alpha = 1.0f; - } - break; - - case DXGI_FORMAT_R16G16B16A16_FLOAT: - { - outColor->red = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 0)); - outColor->green = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 1)); - outColor->blue = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 2)); - outColor->alpha = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 3)); - } - break; - - case DXGI_FORMAT_B8G8R8A8_UNORM: - { - unsigned int bgra = *reinterpret_cast(data + 4 * x + y * inputPitch); - outColor->red = (bgra & 0x00FF0000) * (1.0f / 0x00FF0000); - outColor->blue = (bgra & 0x000000FF) * (1.0f / 0x000000FF); - outColor->green = (bgra & 0x0000FF00) * (1.0f / 0x0000FF00); - outColor->alpha = (bgra & 0xFF000000) * (1.0f / 0xFF000000); - } - break; - - case DXGI_FORMAT_R8_UNORM: - { - outColor->red = *(data + x + y * inputPitch) / 255.0f; - outColor->green = 0.0f; - outColor->blue = 0.0f; - outColor->alpha = 1.0f; - } - break; - - case DXGI_FORMAT_R8G8_UNORM: - { - unsigned short rg = *reinterpret_cast(data + 2 * x + y * inputPitch); - - outColor->red = (rg & 0xFF00) * (1.0f / 0xFF00); - outColor->green = (rg & 0x00FF) * (1.0f / 0x00FF); - outColor->blue = 0.0f; - outColor->alpha = 1.0f; - } - break; - - case DXGI_FORMAT_R16_FLOAT: - { - outColor->red = gl::float16ToFloat32(*reinterpret_cast(data + 2 * x + y * inputPitch)); - outColor->green = 0.0f; - outColor->blue = 0.0f; - outColor->alpha = 1.0f; - } - break; - - case DXGI_FORMAT_R16G16_FLOAT: - { - outColor->red = gl::float16ToFloat32(*(reinterpret_cast(data + 4 * x + y * inputPitch) + 0)); - outColor->green = gl::float16ToFloat32(*(reinterpret_cast(data + 4 * x + y * inputPitch) + 1)); - outColor->blue = 0.0f; - outColor->alpha = 1.0f; - } - break; - - default: - ERR("ReadPixelColor not implemented for DXGI format %u.", format); - UNIMPLEMENTED(); - break; - } -} - -static inline void writePixelColor(const gl::Color &color, GLenum format, GLenum type, unsigned int x, - unsigned int y, int outputPitch, void *outData) -{ - unsigned char* byteData = reinterpret_cast(outData); - unsigned short* shortData = reinterpret_cast(outData); - - switch (format) - { - case GL_RGBA: - switch (type) - { - case GL_UNSIGNED_BYTE: - byteData[4 * x + y * outputPitch + 0] = static_cast(255 * color.red + 0.5f); - byteData[4 * x + y * outputPitch + 1] = static_cast(255 * color.green + 0.5f); - byteData[4 * x + y * outputPitch + 2] = static_cast(255 * color.blue + 0.5f); - byteData[4 * x + y * outputPitch + 3] = static_cast(255 * color.alpha + 0.5f); - break; - - default: - ERR("WritePixelColor not implemented for format GL_RGBA and type 0x%X.", type); - UNIMPLEMENTED(); - break; - } - break; - - case GL_BGRA_EXT: - switch (type) - { - case GL_UNSIGNED_BYTE: - byteData[4 * x + y * outputPitch + 0] = static_cast(255 * color.blue + 0.5f); - byteData[4 * x + y * outputPitch + 1] = static_cast(255 * color.green + 0.5f); - byteData[4 * x + y * outputPitch + 2] = static_cast(255 * color.red + 0.5f); - byteData[4 * x + y * outputPitch + 3] = static_cast(255 * color.alpha + 0.5f); - break; - - case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - shortData[x + y * outputPitch / sizeof(unsigned short)] = - (static_cast(15 * color.alpha + 0.5f) << 12) | - (static_cast(15 * color.red + 0.5f) << 8) | - (static_cast(15 * color.green + 0.5f) << 4) | - (static_cast(15 * color.blue + 0.5f) << 0); - break; - - case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - shortData[x + y * outputPitch / sizeof(unsigned short)] = - (static_cast( color.alpha + 0.5f) << 15) | - (static_cast(31 * color.red + 0.5f) << 10) | - (static_cast(31 * color.green + 0.5f) << 5) | - (static_cast(31 * color.blue + 0.5f) << 0); - break; - - default: - ERR("WritePixelColor not implemented for format GL_BGRA_EXT and type 0x%X.", type); - UNIMPLEMENTED(); - break; - } - break; - - case GL_RGB: - switch (type) - { - case GL_UNSIGNED_SHORT_5_6_5: - shortData[x + y * outputPitch / sizeof(unsigned short)] = - (static_cast(31 * color.blue + 0.5f) << 0) | - (static_cast(63 * color.green + 0.5f) << 5) | - (static_cast(31 * color.red + 0.5f) << 11); - break; - - case GL_UNSIGNED_BYTE: - byteData[3 * x + y * outputPitch + 0] = static_cast(255 * color.red + 0.5f); - byteData[3 * x + y * outputPitch + 1] = static_cast(255 * color.green + 0.5f); - byteData[3 * x + y * outputPitch + 2] = static_cast(255 * color.blue + 0.5f); - break; - - default: - ERR("WritePixelColor not implemented for format GL_RGB and type 0x%X.", type); - UNIMPLEMENTED(); - break; - } - break; - - default: - ERR("WritePixelColor not implemented for format 0x%X.", format); - UNIMPLEMENTED(); - break; - } -} - -void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, - GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder, - GLint packAlignment, void *pixels) -{ - D3D11_TEXTURE2D_DESC textureDesc; - texture->GetDesc(&textureDesc); - - D3D11_TEXTURE2D_DESC stagingDesc; - stagingDesc.Width = area.width; - stagingDesc.Height = area.height; - stagingDesc.MipLevels = 1; - stagingDesc.ArraySize = 1; - stagingDesc.Format = textureDesc.Format; - stagingDesc.SampleDesc.Count = 1; - stagingDesc.SampleDesc.Quality = 0; - stagingDesc.Usage = D3D11_USAGE_STAGING; - stagingDesc.BindFlags = 0; - stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - stagingDesc.MiscFlags = 0; - - ID3D11Texture2D* stagingTex = NULL; - HRESULT result = mDevice->CreateTexture2D(&stagingDesc, NULL, &stagingTex); - if (FAILED(result)) - { - ERR("Failed to create staging texture for readPixels, HRESULT: 0x%X.", result); - return; - } - - ID3D11Texture2D* srcTex = NULL; - if (textureDesc.SampleDesc.Count > 1) - { - D3D11_TEXTURE2D_DESC resolveDesc; - resolveDesc.Width = textureDesc.Width; - resolveDesc.Height = textureDesc.Height; - resolveDesc.MipLevels = 1; - resolveDesc.ArraySize = 1; - resolveDesc.Format = textureDesc.Format; - resolveDesc.SampleDesc.Count = 1; - resolveDesc.SampleDesc.Quality = 0; - resolveDesc.Usage = D3D11_USAGE_DEFAULT; - resolveDesc.BindFlags = 0; - resolveDesc.CPUAccessFlags = 0; - resolveDesc.MiscFlags = 0; - - result = mDevice->CreateTexture2D(&resolveDesc, NULL, &srcTex); - if (FAILED(result)) - { - ERR("Failed to create resolve texture for readPixels, HRESULT: 0x%X.", result); - stagingTex->Release(); - return; - } - - mDeviceContext->ResolveSubresource(srcTex, 0, texture, subResource, textureDesc.Format); - subResource = 0; - } - else - { - srcTex = texture; - srcTex->AddRef(); - } - - D3D11_BOX srcBox; - srcBox.left = area.x; - srcBox.right = area.x + area.width; - srcBox.top = area.y; - srcBox.bottom = area.y + area.height; - srcBox.front = 0; - srcBox.back = 1; - - mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox); - - srcTex->Release(); - srcTex = NULL; - - D3D11_MAPPED_SUBRESOURCE mapping; - mDeviceContext->Map(stagingTex, 0, D3D11_MAP_READ, 0, &mapping); - - unsigned char *source; - int inputPitch; - if (packReverseRowOrder) - { - source = static_cast(mapping.pData) + mapping.RowPitch * (area.height - 1); - inputPitch = -static_cast(mapping.RowPitch); - } - else - { - source = static_cast(mapping.pData); - inputPitch = static_cast(mapping.RowPitch); - } - - unsigned int fastPixelSize = getFastPixelCopySize(textureDesc.Format, format, type); - if (fastPixelSize != 0) - { - unsigned char *dest = static_cast(pixels); - for (int j = 0; j < area.height; j++) - { - memcpy(dest + j * outputPitch, source + j * inputPitch, area.width * fastPixelSize); - } - } - else if (textureDesc.Format == DXGI_FORMAT_B8G8R8A8_UNORM && - format == GL_RGBA && - type == GL_UNSIGNED_BYTE) - { - // Fast path for swapping red with blue - unsigned char *dest = static_cast(pixels); - - for (int j = 0; j < area.height; j++) - { - for (int i = 0; i < area.width; i++) - { - unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); - *(unsigned int*)(dest + 4 * i + j * outputPitch) = - (argb & 0xFF00FF00) | // Keep alpha and green - (argb & 0x00FF0000) >> 16 | // Move red to blue - (argb & 0x000000FF) << 16; // Move blue to red - } - } - } - else - { - gl::Color pixelColor; - for (int j = 0; j < area.height; j++) - { - for (int i = 0; i < area.width; i++) - { - readPixelColor(source, textureDesc.Format, i, j, inputPitch, &pixelColor); - writePixelColor(pixelColor, format, type, i, j, outputPitch, pixels); - } - } - } - - mDeviceContext->Unmap(stagingTex, 0); - - stagingTex->Release(); - stagingTex = NULL; -} - -bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, - RenderTarget *drawRenderTarget, bool wholeBufferCopy) -{ - ASSERT(readRect.width == drawRect.width && readRect.height == drawRect.height); - - RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget); - if (!drawRenderTarget) - { - ERR("Failed to retrieve the draw render target from the draw framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - ID3D11Texture2D *drawTexture = drawRenderTarget11->getTexture(); - unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); - - RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget); - if (!readRenderTarget) - { - ERR("Failed to retrieve the read render target from the read framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - ID3D11Texture2D *readTexture = NULL; - unsigned int readSubresource = 0; - if (readRenderTarget->getSamples() > 0) - { - readTexture = resolveMultisampledTexture(readRenderTarget11->getTexture(), readRenderTarget11->getSubresourceIndex()); - readSubresource = 0; - } - else - { - readTexture = readRenderTarget11->getTexture(); - readTexture->AddRef(); - readSubresource = readRenderTarget11->getSubresourceIndex(); - } - - if (!readTexture) - { - ERR("Failed to retrieve the read render target view from the read render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - D3D11_BOX readBox; - readBox.left = readRect.x; - readBox.right = readRect.x + readRect.width; - readBox.top = readRect.y; - readBox.bottom = readRect.y + readRect.height; - readBox.front = 0; - readBox.back = 1; - - // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox - // We also require complete framebuffer copies for depth-stencil blit. - D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox; - - mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, drawRect.x, drawRect.y, 0, - readTexture, readSubresource, pSrcBox); - - SafeRelease(readTexture); - - return true; -} - -ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource) -{ - D3D11_TEXTURE2D_DESC textureDesc; - source->GetDesc(&textureDesc); - - if (textureDesc.SampleDesc.Count > 1) - { - D3D11_TEXTURE2D_DESC resolveDesc; - resolveDesc.Width = textureDesc.Width; - resolveDesc.Height = textureDesc.Height; - resolveDesc.MipLevels = 1; - resolveDesc.ArraySize = 1; - resolveDesc.Format = textureDesc.Format; - resolveDesc.SampleDesc.Count = 1; - resolveDesc.SampleDesc.Quality = 0; - resolveDesc.Usage = textureDesc.Usage; - resolveDesc.BindFlags = textureDesc.BindFlags; - resolveDesc.CPUAccessFlags = 0; - resolveDesc.MiscFlags = 0; - - ID3D11Texture2D *resolveTexture = NULL; - HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture); - if (FAILED(result)) - { - ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result); - return NULL; - } - - mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format); - return resolveTexture; - } - else - { - source->AddRef(); - return source; - } -} - -bool Renderer11::getLUID(LUID *adapterLuid) const -{ - adapterLuid->HighPart = 0; - adapterLuid->LowPart = 0; - - if (!mDxgiAdapter) - { - return false; - } - - DXGI_ADAPTER_DESC adapterDesc; - if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc))) - { - return false; - } - - *adapterLuid = adapterDesc.AdapterLuid; - return true; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h deleted file mode 100644 index 433945da7a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h +++ /dev/null @@ -1,360 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Renderer11.h: Defines a back-end specific class for the D3D11 renderer. - -#ifndef LIBGLESV2_RENDERER_RENDERER11_H_ -#define LIBGLESV2_RENDERER_RENDERER11_H_ - -#include "common/angleutils.h" -#include "libGLESv2/angletypes.h" -#include "libGLESv2/mathutil.h" - -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/RenderStateCache.h" -#include "libGLESv2/renderer/InputLayoutCache.h" -#include "libGLESv2/renderer/RenderTarget.h" - -namespace gl -{ -class Renderbuffer; -} - -namespace rx -{ - -class VertexDataManager; -class IndexDataManager; -class StreamingIndexBufferInterface; - -enum -{ - MAX_VERTEX_UNIFORM_VECTORS_D3D9 = 254, - MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024, - MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024 -}; - -class Renderer11 : public Renderer -{ - public: - Renderer11(egl::Display *display, HDC hDc); - virtual ~Renderer11(); - - static Renderer11 *makeRenderer11(Renderer *renderer); - - virtual EGLint initialize(); - virtual bool resetDevice(); - - virtual int generateConfigs(ConfigDesc **configDescList); - virtual void deleteConfigs(ConfigDesc *configDescList); - - virtual void sync(bool block); - - virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); - - virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); - virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture); - - virtual void setRasterizerState(const gl::RasterizerState &rasterState); - virtual void setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, - unsigned int sampleMask); - virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW); - - virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); - virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport); - - virtual bool applyPrimitiveType(GLenum mode, GLsizei count); - virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer); - virtual void applyShaders(gl::ProgramBinary *programBinary); - virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray); - virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances); - virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); - - virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances); - virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); - - virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); - - virtual void markAllStateDirty(); - - // lost device - void notifyDeviceLost(); - virtual bool isDeviceLost(); - virtual bool testDeviceLost(bool notify); - virtual bool testDeviceResettable(); - - // Renderer capabilities - virtual DWORD getAdapterVendor() const; - virtual std::string getRendererDescription() const; - virtual GUID getAdapterIdentifier() const; - - virtual bool getBGRATextureSupport() const; - virtual bool getDXT1TextureSupport(); - virtual bool getDXT3TextureSupport(); - virtual bool getDXT5TextureSupport(); - virtual bool getEventQuerySupport(); - virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable); - virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable); - virtual bool getLuminanceTextureSupport(); - virtual bool getLuminanceAlphaTextureSupport(); - virtual unsigned int getMaxVertexTextureImageUnits() const; - virtual unsigned int getMaxCombinedTextureImageUnits() const; - virtual unsigned int getReservedVertexUniformVectors() const; - virtual unsigned int getReservedFragmentUniformVectors() const; - virtual unsigned int getMaxVertexUniformVectors() const; - virtual unsigned int getMaxFragmentUniformVectors() const; - virtual unsigned int getMaxVaryingVectors() const; - virtual bool getNonPower2TextureSupport() const; - virtual bool getDepthTextureSupport() const; - virtual bool getOcclusionQuerySupport() const; - virtual bool getInstancingSupport() const; - virtual bool getTextureFilterAnisotropySupport() const; - virtual float getTextureMaxAnisotropy() const; - virtual bool getShareHandleSupport() const; - virtual bool getDerivativeInstructionSupport() const; - virtual bool getPostSubBufferSupport() const; - - virtual int getMajorShaderModel() const; - virtual float getMaxPointSize() const; - virtual int getMaxViewportDimension() const; - virtual int getMaxTextureWidth() const; - virtual int getMaxTextureHeight() const; - virtual bool get32BitIndexSupport() const; - virtual int getMinSwapInterval() const; - virtual int getMaxSwapInterval() const; - - virtual GLsizei getMaxSupportedSamples() const; - int getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const; - - virtual unsigned int getMaxRenderTargets() const; - - // Pixel operations - virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source); - virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source); - - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level); - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level); - - bool copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight, - ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat); - - virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - bool blitRenderTarget, bool blitDepthStencil); - virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels); - - // RenderTarget creation - virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); - virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth); - - // Shader operations - virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type); - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type); - - // Image operations - virtual Image *createImage(); - virtual void generateMipmap(Image *dest, Image *source); - virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); - virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); - virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); - - // Buffer creation - virtual VertexBuffer *createVertexBuffer(); - virtual IndexBuffer *createIndexBuffer(); - virtual BufferStorage *createBufferStorage(); - - // Query and Fence creation - virtual QueryImpl *createQuery(GLenum type); - virtual FenceImpl *createFence(); - - // D3D11-renderer specific methods - ID3D11Device *getDevice() { return mDevice; } - ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; - IDXGIFactory *getDxgiFactory() { return mDxgiFactory; }; - D3D_FEATURE_LEVEL getFeatureLevel() const { return mFeatureLevel; } - - bool getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource); - void unapplyRenderTargets(); - void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView); - - virtual bool getLUID(LUID *adapterLuid) const; - - private: - DISALLOW_COPY_AND_ASSIGN(Renderer11); - - void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); - void drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances); - - void readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, - GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder, - GLint packAlignment, void *pixels); - - void maskedClear(const gl::ClearParameters &clearParams, bool usingExtendedDrawBuffers); - rx::Range getViewportBounds() const; - - bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, - RenderTarget *drawRenderTarget, bool wholeBufferCopy); - ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); - - HMODULE mD3d11Module; - HMODULE mDxgiModule; - HDC mDc; - - bool mDeviceLost; - - void initializeDevice(); - void releaseDeviceResources(); - int getMinorShaderModel() const; - void release(); - - RenderStateCache mStateCache; - - // Support flags - bool mFloat16TextureSupport; - bool mFloat16FilterSupport; - bool mFloat16RenderSupport; - - bool mFloat32TextureSupport; - bool mFloat32FilterSupport; - bool mFloat32RenderSupport; - - bool mDXT1TextureSupport; - bool mDXT3TextureSupport; - bool mDXT5TextureSupport; - - bool mDepthTextureSupport; - - // Multisample format support - struct MultisampleSupportInfo - { - unsigned int qualityLevels[D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT]; - }; - - typedef std::unordered_map MultisampleSupportMap; - MultisampleSupportMap mMultisampleSupportMap; - - unsigned int mMaxSupportedSamples; - - // current render target states - unsigned int mAppliedRenderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; - unsigned int mAppliedDepthbufferSerial; - unsigned int mAppliedStencilbufferSerial; - bool mDepthStencilInitialized; - bool mRenderTargetDescInitialized; - rx::RenderTarget::Desc mRenderTargetDesc; - unsigned int mCurDepthSize; - unsigned int mCurStencilSize; - - // Currently applied sampler states - bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - gl::SamplerState mCurVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - - bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; - gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; - - // Currently applied textures - unsigned int mCurVertexTextureSerials[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS]; - - // Currently applied blend state - bool mForceSetBlendState; - gl::BlendState mCurBlendState; - gl::Color mCurBlendColor; - unsigned int mCurSampleMask; - - // Currently applied rasterizer state - bool mForceSetRasterState; - gl::RasterizerState mCurRasterState; - - // Currently applied depth stencil state - bool mForceSetDepthStencilState; - gl::DepthStencilState mCurDepthStencilState; - int mCurStencilRef; - int mCurStencilBackRef; - - // Currently applied scissor rectangle - bool mForceSetScissor; - bool mScissorEnabled; - gl::Rectangle mCurScissor; - - // Currently applied viewport - bool mForceSetViewport; - gl::Rectangle mCurViewport; - float mCurNear; - float mCurFar; - - // Currently applied primitive topology - D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology; - - unsigned int mAppliedIBSerial; - unsigned int mAppliedStorageIBSerial; - unsigned int mAppliedIBOffset; - - unsigned int mAppliedProgramBinarySerial; - bool mIsGeometryShaderActive; - - dx_VertexConstants mVertexConstants; - dx_VertexConstants mAppliedVertexConstants; - ID3D11Buffer *mDriverConstantBufferVS; - ID3D11Buffer *mCurrentVertexConstantBuffer; - - dx_PixelConstants mPixelConstants; - dx_PixelConstants mAppliedPixelConstants; - ID3D11Buffer *mDriverConstantBufferPS; - ID3D11Buffer *mCurrentPixelConstantBuffer; - - ID3D11Buffer *mCurrentGeometryConstantBuffer; - - // Vertex, index and input layouts - VertexDataManager *mVertexDataManager; - IndexDataManager *mIndexDataManager; - InputLayoutCache mInputLayoutCache; - - StreamingIndexBufferInterface *mLineLoopIB; - StreamingIndexBufferInterface *mTriangleFanIB; - - // Texture copy resources - bool mCopyResourcesInitialized; - ID3D11Buffer *mCopyVB; - ID3D11SamplerState *mCopySampler; - ID3D11InputLayout *mCopyIL; - ID3D11VertexShader *mCopyVS; - ID3D11PixelShader *mCopyRGBAPS; - ID3D11PixelShader *mCopyRGBPS; - ID3D11PixelShader *mCopyLumPS; - ID3D11PixelShader *mCopyLumAlphaPS; - - // Masked clear resources - bool mClearResourcesInitialized; - ID3D11Buffer *mClearVB; - ID3D11InputLayout *mClearIL; - ID3D11VertexShader *mClearVS; - ID3D11PixelShader *mClearSinglePS; - ID3D11PixelShader *mClearMultiplePS; - ID3D11RasterizerState *mClearScissorRS; - ID3D11RasterizerState *mClearNoScissorRS; - - // Sync query - ID3D11Query *mSyncQuery; - - ID3D11Device *mDevice; - D3D_FEATURE_LEVEL mFeatureLevel; - ID3D11DeviceContext *mDeviceContext; - IDXGIAdapter *mDxgiAdapter; - DXGI_ADAPTER_DESC mAdapterDescription; - char mDescription[128]; - IDXGIFactory *mDxgiFactory; - - // Cached device caps - bool mBGRATextureSupport; -}; - -} -#endif // LIBGLESV2_RENDERER_RENDERER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp deleted file mode 100644 index d3f3814ae5..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp +++ /dev/null @@ -1,3260 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer. - -#include "libGLESv2/main.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/renderer/IndexDataManager.h" -#include "libGLESv2/renderer/Renderer9.h" -#include "libGLESv2/renderer/renderer9_utils.h" -#include "libGLESv2/renderer/ShaderExecutable9.h" -#include "libGLESv2/renderer/SwapChain9.h" -#include "libGLESv2/renderer/TextureStorage9.h" -#include "libGLESv2/renderer/Image9.h" -#include "libGLESv2/renderer/Blit.h" -#include "libGLESv2/renderer/RenderTarget9.h" -#include "libGLESv2/renderer/VertexBuffer9.h" -#include "libGLESv2/renderer/IndexBuffer9.h" -#include "libGLESv2/renderer/BufferStorage9.h" -#include "libGLESv2/renderer/Query9.h" -#include "libGLESv2/renderer/Fence9.h" - -#include "libEGL/Display.h" - -#include "third_party/trace_event/trace_event.h" - -// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros -#define REF_RAST 0 - -// The "Debug This Pixel..." feature in PIX often fails when using the -// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7 -// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file. -#if !defined(ANGLE_ENABLE_D3D9EX) -// Enables use of the IDirect3D9Ex interface, when available -#define ANGLE_ENABLE_D3D9EX 1 -#endif // !defined(ANGLE_ENABLE_D3D9EX) - -namespace rx -{ -static const D3DFORMAT RenderTargetFormats[] = - { - D3DFMT_A1R5G5B5, - // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value. - D3DFMT_A8R8G8B8, - D3DFMT_R5G6B5, - // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format - D3DFMT_X8R8G8B8 - }; - -static const D3DFORMAT DepthStencilFormats[] = - { - D3DFMT_UNKNOWN, - // D3DFMT_D16_LOCKABLE, - D3DFMT_D32, - // D3DFMT_D15S1, - D3DFMT_D24S8, - D3DFMT_D24X8, - // D3DFMT_D24X4S4, - D3DFMT_D16, - // D3DFMT_D32F_LOCKABLE, - // D3DFMT_D24FS8 - }; - -enum -{ - MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256, - MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32, - MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224, - MAX_VARYING_VECTORS_SM2 = 8, - MAX_VARYING_VECTORS_SM3 = 10, - - MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4 -}; - -Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Renderer(display), mDc(hDc), mSoftwareDevice(softwareDevice) -{ - mD3d9Module = NULL; - - mD3d9 = NULL; - mD3d9Ex = NULL; - mDevice = NULL; - mDeviceEx = NULL; - mDeviceWindow = NULL; - mBlit = NULL; - - mAdapter = D3DADAPTER_DEFAULT; - - #if REF_RAST == 1 || defined(FORCE_REF_RAST) - mDeviceType = D3DDEVTYPE_REF; - #else - mDeviceType = D3DDEVTYPE_HAL; - #endif - - mDeviceLost = false; - - mMaxSupportedSamples = 0; - - mMaskedClearSavedState = NULL; - - mVertexDataManager = NULL; - mIndexDataManager = NULL; - mLineLoopIB = NULL; - - mMaxNullColorbufferLRU = 0; - for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) - { - mNullColorbufferCache[i].lruCount = 0; - mNullColorbufferCache[i].width = 0; - mNullColorbufferCache[i].height = 0; - mNullColorbufferCache[i].buffer = NULL; - } -} - -Renderer9::~Renderer9() -{ - releaseDeviceResources(); - - if (mDevice) - { - // If the device is lost, reset it first to prevent leaving the driver in an unstable state - if (testDeviceLost(false)) - { - resetDevice(); - } - - mDevice->Release(); - mDevice = NULL; - } - - if (mDeviceEx) - { - mDeviceEx->Release(); - mDeviceEx = NULL; - } - - if (mD3d9) - { - mD3d9->Release(); - mD3d9 = NULL; - } - - if (mDeviceWindow) - { - DestroyWindow(mDeviceWindow); - mDeviceWindow = NULL; - } - - if (mD3d9Ex) - { - mD3d9Ex->Release(); - mD3d9Ex = NULL; - } - - if (mD3d9Module) - { - mD3d9Module = NULL; - } - - while (!mMultiSampleSupport.empty()) - { - delete [] mMultiSampleSupport.begin()->second; - mMultiSampleSupport.erase(mMultiSampleSupport.begin()); - } -} - -Renderer9 *Renderer9::makeRenderer9(Renderer *renderer) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer9*, renderer)); - return static_cast(renderer); -} - -EGLint Renderer9::initialize() -{ - if (!initializeCompiler()) - { - return EGL_NOT_INITIALIZED; - } - - if (mSoftwareDevice) - { - TRACE_EVENT0("gpu", "GetModuleHandle_swiftshader"); - mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); - } - else - { - TRACE_EVENT0("gpu", "GetModuleHandle_d3d9"); - mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); - } - - if (mD3d9Module == NULL) - { - ERR("No D3D9 module found - aborting!\n"); - return EGL_NOT_INITIALIZED; - } - - typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); - Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); - - // Use Direct3D9Ex if available. Among other things, this version is less - // inclined to report a lost context, for example when the user switches - // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. - if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) - { - TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface"); - ASSERT(mD3d9Ex); - mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast(&mD3d9)); - ASSERT(mD3d9); - } - else - { - TRACE_EVENT0("gpu", "Direct3DCreate9"); - mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); - } - - if (!mD3d9) - { - ERR("Could not create D3D9 device - aborting!\n"); - return EGL_NOT_INITIALIZED; - } - - if (mDc != NULL) - { - // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to - } - - HRESULT result; - - // Give up on getting device caps after about one second. - { - TRACE_EVENT0("gpu", "GetDeviceCaps"); - for (int i = 0; i < 10; ++i) - { - result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); - if (SUCCEEDED(result)) - { - break; - } - else if (result == D3DERR_NOTAVAILABLE) - { - Sleep(100); // Give the driver some time to initialize/recover - } - else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from - { - ERR("failed to get device caps (0x%x)\n", result); - return EGL_NOT_INITIALIZED; - } - } - } - - if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0)) - { - ERR("Renderer does not support PS 2.0. aborting!\n"); - return EGL_NOT_INITIALIZED; - } - - // 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) - { - ERR("Renderer does not support stretctrect from textures!\n"); - return EGL_NOT_INITIALIZED; - } - - { - TRACE_EVENT0("gpu", "GetAdapterIdentifier"); - mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); - } - - // ATI cards on XP have problems with non-power-of-two textures. - mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && - !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && - !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) && - !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD); - - // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec - mSupportsTextureFilterAnisotropy = ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2)); - - mMinSwapInterval = 4; - mMaxSwapInterval = 0; - - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) - { - mMinSwapInterval = std::min(mMinSwapInterval, 0); - mMaxSwapInterval = std::max(mMaxSwapInterval, 0); - } - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) - { - mMinSwapInterval = std::min(mMinSwapInterval, 1); - mMaxSwapInterval = std::max(mMaxSwapInterval, 1); - } - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) - { - mMinSwapInterval = std::min(mMinSwapInterval, 2); - mMaxSwapInterval = std::max(mMaxSwapInterval, 2); - } - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) - { - mMinSwapInterval = std::min(mMinSwapInterval, 3); - mMaxSwapInterval = std::max(mMaxSwapInterval, 3); - } - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) - { - mMinSwapInterval = std::min(mMinSwapInterval, 4); - mMaxSwapInterval = std::max(mMaxSwapInterval, 4); - } - - int max = 0; - { - TRACE_EVENT0("gpu", "getMultiSampleSupport"); - for (unsigned int i = 0; i < ArraySize(RenderTargetFormats); ++i) - { - bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; - getMultiSampleSupport(RenderTargetFormats[i], multisampleArray); - mMultiSampleSupport[RenderTargetFormats[i]] = multisampleArray; - - for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) - { - if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) - { - max = j; - } - } - } - } - - { - TRACE_EVENT0("gpu", "getMultiSampleSupport2"); - for (unsigned int i = 0; i < ArraySize(DepthStencilFormats); ++i) - { - if (DepthStencilFormats[i] == D3DFMT_UNKNOWN) - continue; - - bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; - getMultiSampleSupport(DepthStencilFormats[i], multisampleArray); - mMultiSampleSupport[DepthStencilFormats[i]] = multisampleArray; - - for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) - { - if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) - { - max = j; - } - } - } - } - - mMaxSupportedSamples = max; - - static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); - static const TCHAR className[] = TEXT("STATIC"); - - { - TRACE_EVENT0("gpu", "CreateWindowEx"); - mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); - } - - D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); - DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES; - - { - TRACE_EVENT0("gpu", "D3d9_CreateDevice"); - result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); - } - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) - { - return EGL_BAD_ALLOC; - } - - if (FAILED(result)) - { - TRACE_EVENT0("gpu", "D3d9_CreateDevice2"); - result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST); - return EGL_BAD_ALLOC; - } - } - - if (mD3d9Ex) - { - TRACE_EVENT0("gpu", "mDevice_QueryInterface"); - result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx); - ASSERT(SUCCEEDED(result)); - } - - { - TRACE_EVENT0("gpu", "ShaderCache initialize"); - mVertexShaderCache.initialize(mDevice); - mPixelShaderCache.initialize(mDevice); - } - - // Check occlusion query support - IDirect3DQuery9 *occlusionQuery = NULL; - { - TRACE_EVENT0("gpu", "device_CreateQuery"); - if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery) - { - occlusionQuery->Release(); - mOcclusionQuerySupport = true; - } - else - { - mOcclusionQuerySupport = false; - } - } - - // Check event query support - IDirect3DQuery9 *eventQuery = NULL; - { - TRACE_EVENT0("gpu", "device_CreateQuery2"); - if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery) - { - eventQuery->Release(); - mEventQuerySupport = true; - } - else - { - mEventQuerySupport = false; - } - } - - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - // Check vertex texture support - // Only Direct3D 10 ready devices support all the necessary vertex texture formats. - // We test this using D3D9 by checking support for the R16F format. - mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, - D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F)); - - // Check depth texture support - // we use INTZ for depth textures in Direct3D9 - // we also want NULL texture support to ensure the we can make depth-only FBOs - // see http://aras-p.info/texts/D3D9GPUHacks.html - mDepthTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, - D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, - D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL)); - - // Check 32 bit floating point texture support - mFloat32FilterSupport = 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)); - - mFloat32RenderSupport = 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 (!mFloat32FilterSupport && !mFloat32RenderSupport) - { - mFloat32TextureSupport = 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 - { - mFloat32TextureSupport = true; - } - - // Check 16 bit floating point texture support - mFloat16FilterSupport = 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)); - - mFloat16RenderSupport = 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 (!mFloat16FilterSupport && !mFloat16RenderSupport) - { - mFloat16TextureSupport = 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 - { - mFloat16TextureSupport = true; - } - - // Check DXT texture support - mDXT1TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1)); - mDXT3TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3)); - mDXT5TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5)); - - // Check luminance[alpha] texture support - mLuminanceTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8)); - mLuminanceAlphaTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8)); - - initializeDevice(); - - return EGL_SUCCESS; -} - -// do any one-time device initialization -// NOTE: this is also needed after a device lost/reset -// to reset the scene status and ensure the default states are reset. -void Renderer9::initializeDevice() -{ - // Permanent non-default states - mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); - mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE); - - if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) - { - mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize); - } - else - { - mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f - } - - markAllStateDirty(); - - mSceneStarted = false; - - ASSERT(!mBlit && !mVertexDataManager && !mIndexDataManager); - mBlit = new Blit(this); - mVertexDataManager = new rx::VertexDataManager(this); - mIndexDataManager = new rx::IndexDataManager(this); -} - -D3DPRESENT_PARAMETERS Renderer9::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; -} - -int Renderer9::generateConfigs(ConfigDesc **configDescList) -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - unsigned int numRenderFormats = ArraySize(RenderTargetFormats); - unsigned int numDepthFormats = ArraySize(DepthStencilFormats); - (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats]; - int numConfigs = 0; - - for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) - { - D3DFORMAT renderTargetFormat = RenderTargetFormats[formatIndex]; - - HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat); - - if (SUCCEEDED(result)) - { - for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) - { - D3DFORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex]; - HRESULT result = D3D_OK; - - if(depthStencilFormat != D3DFMT_UNKNOWN) - { - result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat); - } - - if (SUCCEEDED(result)) - { - if(depthStencilFormat != D3DFMT_UNKNOWN) - { - result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat); - } - - if (SUCCEEDED(result)) - { - ConfigDesc newConfig; - newConfig.renderTargetFormat = d3d9_gl::ConvertBackBufferFormat(renderTargetFormat); - newConfig.depthStencilFormat = d3d9_gl::ConvertDepthStencilFormat(depthStencilFormat); - newConfig.multiSample = 0; // FIXME: enumerate multi-sampling - newConfig.fastConfig = (currentDisplayMode.Format == renderTargetFormat); - - (*configDescList)[numConfigs++] = newConfig; - } - } - } - } - } - - return numConfigs; -} - -void Renderer9::deleteConfigs(ConfigDesc *configDescList) -{ - delete [] (configDescList); -} - -void Renderer9::startScene() -{ - if (!mSceneStarted) - { - long result = mDevice->BeginScene(); - if (SUCCEEDED(result)) { - // This is defensive checking against the device being - // lost at unexpected times. - mSceneStarted = true; - } - } -} - -void Renderer9::endScene() -{ - if (mSceneStarted) - { - // EndScene can fail if the device was lost, for example due - // to a TDR during a draw call. - mDevice->EndScene(); - mSceneStarted = false; - } -} - -void Renderer9::sync(bool block) -{ - HRESULT result; - - IDirect3DQuery9* query = allocateEventQuery(); - if (!query) - { - return; - } - - result = query->Issue(D3DISSUE_END); - ASSERT(SUCCEEDED(result)); - - do - { - result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); - - if(block && result == S_FALSE) - { - // Keep polling, but allow other threads to do something useful first - Sleep(0); - // explicitly check for device loss - // some drivers seem to return S_FALSE even if the device is lost - // instead of D3DERR_DEVICELOST like they should - if (testDeviceLost(false)) - { - result = D3DERR_DEVICELOST; - } - } - } - while(block && result == S_FALSE); - - freeEventQuery(query); - - if (d3d9::isDeviceLostError(result)) - { - notifyDeviceLost(); - } -} - -SwapChain *Renderer9::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) -{ - return new rx::SwapChain9(this, window, shareHandle, backBufferFormat, depthBufferFormat); -} - -IDirect3DQuery9* Renderer9::allocateEventQuery() -{ - IDirect3DQuery9 *query = NULL; - - if (mEventQueryPool.empty()) - { - HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query); - ASSERT(SUCCEEDED(result)); - } - else - { - query = mEventQueryPool.back(); - mEventQueryPool.pop_back(); - } - - return query; -} - -void Renderer9::freeEventQuery(IDirect3DQuery9* query) -{ - if (mEventQueryPool.size() > 1000) - { - query->Release(); - } - else - { - mEventQueryPool.push_back(query); - } -} - -IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length) -{ - return mVertexShaderCache.create(function, length); -} - -IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length) -{ - return mPixelShaderCache.create(function, length); -} - -HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer) -{ - D3DPOOL Pool = getBufferPool(Usage); - return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL); -} - -VertexBuffer *Renderer9::createVertexBuffer() -{ - return new VertexBuffer9(this); -} - -HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer) -{ - D3DPOOL Pool = getBufferPool(Usage); - return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL); -} - -IndexBuffer *Renderer9::createIndexBuffer() -{ - return new IndexBuffer9(this); -} - -BufferStorage *Renderer9::createBufferStorage() -{ - return new BufferStorage9(); -} - -QueryImpl *Renderer9::createQuery(GLenum type) -{ - return new Query9(this, type); -} - -FenceImpl *Renderer9::createFence() -{ - return new Fence9(this); -} - -void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) -{ - bool *forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates; - gl::SamplerState *appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates; - - if (forceSetSamplers[index] || memcmp(&samplerState, &appliedSamplers[index], sizeof(gl::SamplerState)) != 0) - { - int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; - int d3dSampler = index + d3dSamplerOffset; - - mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS)); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT)); - - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy)); - D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter; - gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.lodOffset); - if (mSupportsTextureFilterAnisotropy) - { - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy); - } - } - - forceSetSamplers[index] = false; - appliedSamplers[index] = samplerState; -} - -void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture) -{ - int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; - int d3dSampler = index + d3dSamplerOffset; - IDirect3DBaseTexture9 *d3dTexture = NULL; - unsigned int serial = 0; - bool forceSetTexture = false; - - unsigned int *appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials; - - if (texture) - { - TextureStorageInterface *texStorage = texture->getNativeTexture(); - if (texStorage) - { - TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage->getStorageInstance()); - d3dTexture = storage9->getBaseTexture(); - } - // If we get NULL back from getBaseTexture here, something went wrong - // in the texture class and we're unexpectedly missing the d3d texture - ASSERT(d3dTexture != NULL); - - serial = texture->getTextureSerial(); - forceSetTexture = texture->hasDirtyImages(); - } - - if (forceSetTexture || appliedSerials[index] != serial) - { - mDevice->SetTexture(d3dSampler, d3dTexture); - } - - appliedSerials[index] = serial; -} - -void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState) -{ - bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0; - - if (rasterStateChanged) - { - // Set the cull mode - if (rasterState.cullFace) - { - mDevice->SetRenderState(D3DRS_CULLMODE, gl_d3d9::ConvertCullMode(rasterState.cullMode, rasterState.frontFace)); - } - else - { - mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - } - - if (rasterState.polygonOffsetFill) - { - if (mCurDepthSize > 0) - { - mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&rasterState.polygonOffsetFactor); - - float depthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast(mCurDepthSize)); - mDevice->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD*)&depthBias); - } - } - else - { - mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); - mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0); - } - - mCurRasterState = rasterState; - } - - mForceSetRasterState = false; -} - -void Renderer9::setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask) -{ - bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0; - bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0; - bool sampleMaskChanged = mForceSetBlendState || sampleMask != mCurSampleMask; - - if (blendStateChanged || blendColorChanged) - { - if (blendState.blend) - { - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - - if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && - blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) - { - mDevice->SetRenderState(D3DRS_BLENDFACTOR, gl_d3d9::ConvertColor(blendColor)); - } - else - { - mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha), - gl::unorm<8>(blendColor.alpha), - gl::unorm<8>(blendColor.alpha), - gl::unorm<8>(blendColor.alpha))); - } - - mDevice->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB)); - mDevice->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB)); - mDevice->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB)); - - if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha || - blendState.destBlendRGB != blendState.destBlendAlpha || - blendState.blendEquationRGB != blendState.blendEquationAlpha) - { - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); - - mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha)); - mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha)); - mDevice->SetRenderState(D3DRS_BLENDOPALPHA, gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha)); - } - else - { - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); - } - } - else - { - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - } - - if (blendState.sampleAlphaToCoverage) - { - FIXME("Sample alpha to coverage is unimplemented."); - } - - // Set the color mask - bool zeroColorMaskAllowed = getAdapterVendor() != VENDOR_ID_AMD; - // Apparently some ATI cards have a bug where a draw with a zero color - // write mask can cause later draws to have incorrect results. Instead, - // set a nonzero color write mask but modify the blend state so that no - // drawing is done. - // http://code.google.com/p/angleproject/issues/detail?id=169 - - DWORD colorMask = gl_d3d9::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen, - blendState.colorMaskBlue, blendState.colorMaskAlpha); - if (colorMask == 0 && !zeroColorMaskAllowed) - { - // Enable green channel, but set blending so nothing will be drawn. - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN); - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - - mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); - mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); - mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); - } - else - { - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask); - } - - mDevice->SetRenderState(D3DRS_DITHERENABLE, blendState.dither ? TRUE : FALSE); - - mCurBlendState = blendState; - mCurBlendColor = blendColor; - } - - if (sampleMaskChanged) - { - // Set the multisample mask - mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); - mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast(sampleMask)); - - mCurSampleMask = sampleMask; - } - - mForceSetBlendState = false; -} - -void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW) -{ - bool depthStencilStateChanged = mForceSetDepthStencilState || - memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0; - bool stencilRefChanged = mForceSetDepthStencilState || stencilRef != mCurStencilRef || - stencilBackRef != mCurStencilBackRef; - bool frontFaceCCWChanged = mForceSetDepthStencilState || frontFaceCCW != mCurFrontFaceCCW; - - if (depthStencilStateChanged) - { - if (depthStencilState.depthTest) - { - mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); - mDevice->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthStencilState.depthFunc)); - } - else - { - mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); - } - - mCurDepthStencilState = depthStencilState; - } - - if (depthStencilStateChanged || stencilRefChanged || frontFaceCCWChanged) - { - if (depthStencilState.stencilTest && mCurStencilSize > 0) - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); - mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE); - - // FIXME: Unsupported by D3D9 - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF; - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK; - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK; - if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || - stencilRef != stencilBackRef || - depthStencilState.stencilMask != depthStencilState.stencilBackMask) - { - ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL."); - return gl::error(GL_INVALID_OPERATION); - } - - // get the maximum size of the stencil ref - unsigned int maxStencil = (1 << mCurStencilSize) - 1; - - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, - depthStencilState.stencilWritemask); - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, - gl_d3d9::ConvertComparison(depthStencilState.stencilFunc)); - - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, - (stencilRef < (int)maxStencil) ? stencilRef : maxStencil); - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, - depthStencilState.stencilMask); - - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilFail)); - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthFail)); - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthPass)); - - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, - depthStencilState.stencilBackWritemask); - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, - gl_d3d9::ConvertComparison(depthStencilState.stencilBackFunc)); - - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, - (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil); - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, - depthStencilState.stencilBackMask); - - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackFail)); - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthFail)); - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthPass)); - } - else - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - } - - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, depthStencilState.depthMask ? TRUE : FALSE); - - mCurStencilRef = stencilRef; - mCurStencilBackRef = stencilBackRef; - mCurFrontFaceCCW = frontFaceCCW; - } - - mForceSetDepthStencilState = false; -} - -void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) -{ - bool scissorChanged = mForceSetScissor || - memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || - enabled != mScissorEnabled; - - if (scissorChanged) - { - if (enabled) - { - RECT rect; - rect.left = gl::clamp(scissor.x, 0, static_cast(mRenderTargetDesc.width)); - rect.top = gl::clamp(scissor.y, 0, static_cast(mRenderTargetDesc.height)); - rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast(mRenderTargetDesc.width)); - rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast(mRenderTargetDesc.height)); - mDevice->SetScissorRect(&rect); - } - - mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, enabled ? TRUE : FALSE); - - mScissorEnabled = enabled; - mCurScissor = scissor; - } - - mForceSetScissor = false; -} - -bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport) -{ - gl::Rectangle actualViewport = viewport; - float actualZNear = gl::clamp01(zNear); - float actualZFar = gl::clamp01(zFar); - if (ignoreViewport) - { - actualViewport.x = 0; - actualViewport.y = 0; - actualViewport.width = mRenderTargetDesc.width; - actualViewport.height = mRenderTargetDesc.height; - actualZNear = 0.0f; - actualZFar = 1.0f; - } - - D3DVIEWPORT9 dxViewport; - dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast(mRenderTargetDesc.width)); - dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast(mRenderTargetDesc.height)); - dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast(mRenderTargetDesc.width) - static_cast(dxViewport.X)); - dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast(mRenderTargetDesc.height) - static_cast(dxViewport.Y)); - dxViewport.MinZ = actualZNear; - dxViewport.MaxZ = actualZFar; - - if (dxViewport.Width <= 0 || dxViewport.Height <= 0) - { - return false; // Nothing to render - } - - float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f); - - bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || - actualZNear != mCurNear || actualZFar != mCurFar || mCurDepthFront != depthFront; - if (viewportChanged) - { - mDevice->SetViewport(&dxViewport); - - mCurViewport = actualViewport; - mCurNear = actualZNear; - mCurFar = actualZFar; - mCurDepthFront = depthFront; - - dx_VertexConstants vc = {0}; - dx_PixelConstants pc = {0}; - - vc.viewAdjust[0] = (float)((actualViewport.width - (int)dxViewport.Width) + 2 * (actualViewport.x - (int)dxViewport.X) - 1) / dxViewport.Width; - vc.viewAdjust[1] = (float)((actualViewport.height - (int)dxViewport.Height) + 2 * (actualViewport.y - (int)dxViewport.Y) - 1) / dxViewport.Height; - vc.viewAdjust[2] = (float)actualViewport.width / dxViewport.Width; - vc.viewAdjust[3] = (float)actualViewport.height / dxViewport.Height; - - pc.viewCoords[0] = actualViewport.width * 0.5f; - pc.viewCoords[1] = actualViewport.height * 0.5f; - pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); - pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); - - pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f; - pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f; - pc.depthFront[2] = depthFront; - - vc.depthRange[0] = actualZNear; - vc.depthRange[1] = actualZFar; - vc.depthRange[2] = actualZFar - actualZNear; - - pc.depthRange[0] = actualZNear; - pc.depthRange[1] = actualZFar; - pc.depthRange[2] = actualZFar - actualZNear; - - if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0) - { - mVertexConstants = vc; - mDxUniformsDirty = true; - } - - if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0) - { - mPixelConstants = pc; - mDxUniformsDirty = true; - } - } - - mForceSetViewport = false; - return true; -} - -bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count) -{ - switch (mode) - { - case GL_POINTS: - mPrimitiveType = D3DPT_POINTLIST; - mPrimitiveCount = count; - break; - case GL_LINES: - mPrimitiveType = D3DPT_LINELIST; - mPrimitiveCount = count / 2; - break; - case GL_LINE_LOOP: - mPrimitiveType = D3DPT_LINESTRIP; - mPrimitiveCount = count - 1; // D3D doesn't support line loops, so we draw the last line separately - break; - case GL_LINE_STRIP: - mPrimitiveType = D3DPT_LINESTRIP; - mPrimitiveCount = count - 1; - break; - case GL_TRIANGLES: - mPrimitiveType = D3DPT_TRIANGLELIST; - mPrimitiveCount = count / 3; - break; - case GL_TRIANGLE_STRIP: - mPrimitiveType = D3DPT_TRIANGLESTRIP; - mPrimitiveCount = count - 2; - break; - case GL_TRIANGLE_FAN: - mPrimitiveType = D3DPT_TRIANGLEFAN; - mPrimitiveCount = count - 2; - break; - default: - return gl::error(GL_INVALID_ENUM, false); - } - - return mPrimitiveCount > 0; -} - - -gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer) -{ - if (!depthbuffer) - { - ERR("Unexpected null depthbuffer for depth-only FBO."); - return NULL; - } - - GLsizei width = depthbuffer->getWidth(); - GLsizei height = depthbuffer->getHeight(); - - // search cached nullcolorbuffers - for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) - { - if (mNullColorbufferCache[i].buffer != NULL && - mNullColorbufferCache[i].width == width && - mNullColorbufferCache[i].height == height) - { - mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU; - return mNullColorbufferCache[i].buffer; - } - } - - gl::Renderbuffer *nullbuffer = new gl::Renderbuffer(this, 0, new gl::Colorbuffer(this, width, height, GL_NONE, 0)); - - // add nullbuffer to the cache - NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0]; - for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) - { - if (mNullColorbufferCache[i].lruCount < oldest->lruCount) - { - oldest = &mNullColorbufferCache[i]; - } - } - - delete oldest->buffer; - oldest->buffer = nullbuffer; - oldest->lruCount = ++mMaxNullColorbufferLRU; - oldest->width = width; - oldest->height = height; - - return nullbuffer; -} - -bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) -{ - // if there is no color attachment we must synthesize a NULL colorattachment - // to keep the D3D runtime happy. This should only be possible if depth texturing. - gl::Renderbuffer *renderbufferObject = NULL; - if (framebuffer->getColorbufferType(0) != GL_NONE) - { - renderbufferObject = framebuffer->getColorbuffer(0); - } - else - { - renderbufferObject = getNullColorbuffer(framebuffer->getDepthbuffer()); - } - if (!renderbufferObject) - { - ERR("unable to locate renderbuffer for FBO."); - return false; - } - - bool renderTargetChanged = false; - unsigned int renderTargetSerial = renderbufferObject->getSerial(); - if (renderTargetSerial != mAppliedRenderTargetSerial) - { - // Apply the render target on the device - IDirect3DSurface9 *renderTargetSurface = NULL; - - RenderTarget *renderTarget = renderbufferObject->getRenderTarget(); - if (renderTarget) - { - renderTargetSurface = RenderTarget9::makeRenderTarget9(renderTarget)->getSurface(); - } - - if (!renderTargetSurface) - { - ERR("render target pointer unexpectedly null."); - return false; // Context must be lost - } - - mDevice->SetRenderTarget(0, renderTargetSurface); - renderTargetSurface->Release(); - - mAppliedRenderTargetSerial = renderTargetSerial; - renderTargetChanged = true; - } - - gl::Renderbuffer *depthStencil = NULL; - unsigned int depthbufferSerial = 0; - unsigned int stencilbufferSerial = 0; - if (framebuffer->getDepthbufferType() != GL_NONE) - { - depthStencil = framebuffer->getDepthbuffer(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - return false; - } - - depthbufferSerial = depthStencil->getSerial(); - } - else if (framebuffer->getStencilbufferType() != GL_NONE) - { - depthStencil = framebuffer->getStencilbuffer(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - return false; - } - - stencilbufferSerial = depthStencil->getSerial(); - } - - if (depthbufferSerial != mAppliedDepthbufferSerial || - stencilbufferSerial != mAppliedStencilbufferSerial || - !mDepthStencilInitialized) - { - unsigned int depthSize = 0; - unsigned int stencilSize = 0; - - // Apply the depth stencil on the device - if (depthStencil) - { - IDirect3DSurface9 *depthStencilSurface = NULL; - RenderTarget *depthStencilRenderTarget = depthStencil->getDepthStencil(); - - if (depthStencilRenderTarget) - { - depthStencilSurface = RenderTarget9::makeRenderTarget9(depthStencilRenderTarget)->getSurface(); - } - - if (!depthStencilSurface) - { - ERR("depth stencil pointer unexpectedly null."); - return false; // Context must be lost - } - - mDevice->SetDepthStencilSurface(depthStencilSurface); - depthStencilSurface->Release(); - - depthSize = depthStencil->getDepthSize(); - stencilSize = depthStencil->getStencilSize(); - } - else - { - mDevice->SetDepthStencilSurface(NULL); - } - - if (!mDepthStencilInitialized || depthSize != mCurDepthSize) - { - mCurDepthSize = depthSize; - mForceSetRasterState = true; - } - - if (!mDepthStencilInitialized || stencilSize != mCurStencilSize) - { - mCurStencilSize = stencilSize; - mForceSetDepthStencilState = true; - } - - mAppliedDepthbufferSerial = depthbufferSerial; - mAppliedStencilbufferSerial = stencilbufferSerial; - mDepthStencilInitialized = true; - } - - if (renderTargetChanged || !mRenderTargetDescInitialized) - { - mForceSetScissor = true; - mForceSetViewport = true; - - mRenderTargetDesc.width = renderbufferObject->getWidth(); - mRenderTargetDesc.height = renderbufferObject->getHeight(); - mRenderTargetDesc.format = renderbufferObject->getActualFormat(); - mRenderTargetDescInitialized = true; - } - - return true; -} - -GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) -{ - TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; - GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances); - if (err != GL_NO_ERROR) - { - return err; - } - - return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw); -} - -// Applies the indices and element array bindings to the Direct3D 9 device -GLenum Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) -{ - GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); - - if (err == GL_NO_ERROR) - { - // Directly binding the storage buffer is not supported for d3d9 - ASSERT(indexInfo->storage == NULL); - - if (indexInfo->serial != mAppliedIBSerial) - { - IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer); - - mDevice->SetIndices(indexBuffer->getBuffer()); - mAppliedIBSerial = indexInfo->serial; - } - } - - return err; -} - -void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances) -{ - startScene(); - - if (mode == GL_LINE_LOOP) - { - drawLineLoop(count, GL_NONE, NULL, 0, NULL); - } - else if (instances > 0) - { - StaticIndexBufferInterface *countingIB = mIndexDataManager->getCountingIndices(count); - if (countingIB) - { - if (mAppliedIBSerial != countingIB->getSerial()) - { - IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer()); - - mDevice->SetIndices(indexBuffer->getBuffer()); - mAppliedIBSerial = countingIB->getSerial(); - } - - for (int i = 0; i < mRepeatDraw; i++) - { - mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount); - } - } - else - { - ERR("Could not create a counting index buffer for glDrawArraysInstanced."); - return gl::error(GL_OUT_OF_MEMORY); - } - } - else // Regular case - { - mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount); - } -} - -void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/) -{ - startScene(); - - if (mode == GL_POINTS) - { - drawIndexedPoints(count, type, indices, elementArrayBuffer); - } - else if (mode == GL_LINE_LOOP) - { - drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer); - } - else - { - for (int i = 0; i < mRepeatDraw; i++) - { - GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; - mDevice->DrawIndexedPrimitive(mPrimitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount); - } - } -} - -void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) -{ - // Get the raw indices for an indexed draw - if (type != GL_NONE && elementArrayBuffer) - { - gl::Buffer *indexBuffer = elementArrayBuffer; - BufferStorage *storage = indexBuffer->getStorage(); - intptr_t offset = reinterpret_cast(indices); - indices = static_cast(storage->getData()) + offset; - } - - unsigned int startIndex = 0; - - if (get32BitIndexSupport()) - { - if (!mLineLoopIB) - { - mLineLoopIB = new StreamingIndexBufferInterface(this); - if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) - { - delete mLineLoopIB; - mLineLoopIB = NULL; - - ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - } - - if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned int))) - { - ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); - return gl::error(GL_OUT_OF_MEMORY); - } - - // Checked by Renderer9::applyPrimitiveType - ASSERT(count >= 0); - - const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned int); - if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) - { - ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - - void* mappedMemory = NULL; - unsigned int offset = 0; - if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) - { - ERR("Could not map index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - - startIndex = static_cast(offset) / 4; - unsigned int *data = reinterpret_cast(mappedMemory); - - switch (type) - { - case GL_NONE: // Non-indexed draw - for (int i = 0; i < count; i++) - { - data[i] = i; - } - data[count] = 0; - break; - case GL_UNSIGNED_BYTE: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_SHORT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_INT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - default: UNREACHABLE(); - } - - if (!mLineLoopIB->unmapBuffer()) - { - ERR("Could not unmap index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - } - else - { - if (!mLineLoopIB) - { - mLineLoopIB = new StreamingIndexBufferInterface(this); - if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT)) - { - delete mLineLoopIB; - mLineLoopIB = NULL; - - ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - } - - // Checked by Renderer9::applyPrimitiveType - ASSERT(count >= 0); - - if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned short))) - { - ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required."); - return gl::error(GL_OUT_OF_MEMORY); - } - - const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned short); - if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT)) - { - ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - - void* mappedMemory = NULL; - unsigned int offset; - if (mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) - { - ERR("Could not map index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - - startIndex = static_cast(offset) / 2; - unsigned short *data = reinterpret_cast(mappedMemory); - - switch (type) - { - case GL_NONE: // Non-indexed draw - for (int i = 0; i < count; i++) - { - data[i] = i; - } - data[count] = 0; - break; - case GL_UNSIGNED_BYTE: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_SHORT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_INT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - default: UNREACHABLE(); - } - - if (!mLineLoopIB->unmapBuffer()) - { - ERR("Could not unmap index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - } - - if (mAppliedIBSerial != mLineLoopIB->getSerial()) - { - IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(mLineLoopIB->getIndexBuffer()); - - mDevice->SetIndices(indexBuffer->getBuffer()); - mAppliedIBSerial = mLineLoopIB->getSerial(); - } - - mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count); -} - -template -static void drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices) -{ - for (int i = 0; i < count; i++) - { - unsigned int indexValue = static_cast(static_cast(indices)[i]); - device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1); - } -} - -void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer) -{ - // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call - // for each individual point. This call is not expected to happen often. - - if (elementArrayBuffer) - { - BufferStorage *storage = elementArrayBuffer->getStorage(); - intptr_t offset = reinterpret_cast(indices); - indices = static_cast(storage->getData()) + offset; - } - - switch (type) - { - case GL_UNSIGNED_BYTE: drawPoints(mDevice, count, indices); break; - case GL_UNSIGNED_SHORT: drawPoints(mDevice, count, indices); break; - case GL_UNSIGNED_INT: drawPoints(mDevice, count, indices); break; - default: UNREACHABLE(); - } -} - -void Renderer9::applyShaders(gl::ProgramBinary *programBinary) -{ - unsigned int programBinarySerial = programBinary->getSerial(); - if (programBinarySerial != mAppliedProgramBinarySerial) - { - ShaderExecutable *vertexExe = programBinary->getVertexExecutable(); - ShaderExecutable *pixelExe = programBinary->getPixelExecutable(); - - IDirect3DVertexShader9 *vertexShader = NULL; - if (vertexExe) vertexShader = ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader(); - - IDirect3DPixelShader9 *pixelShader = NULL; - if (pixelExe) pixelShader = ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader(); - - mDevice->SetPixelShader(pixelShader); - mDevice->SetVertexShader(vertexShader); - programBinary->dirtyAllUniforms(); - mDxUniformsDirty = true; - - mAppliedProgramBinarySerial = programBinarySerial; - } -} - -void Renderer9::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) -{ - for (std::vector::const_iterator ub = uniformArray->begin(), ue = uniformArray->end(); ub != ue; ++ub) - { - gl::Uniform *targetUniform = *ub; - - if (targetUniform->dirty) - { - GLfloat *f = (GLfloat*)targetUniform->data; - GLint *i = (GLint*)targetUniform->data; - - switch (targetUniform->type) - { - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: - break; - case GL_BOOL: - case GL_BOOL_VEC2: - case GL_BOOL_VEC3: - case GL_BOOL_VEC4: - applyUniformnbv(targetUniform, i); - break; - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT2: - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT4: - applyUniformnfv(targetUniform, f); - break; - case GL_INT: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_INT_VEC4: - applyUniformniv(targetUniform, i); - break; - default: - UNREACHABLE(); - } - - targetUniform->dirty = false; - } - } - - // Driver uniforms - if (mDxUniformsDirty) - { - mDevice->SetVertexShaderConstantF(0, (float*)&mVertexConstants, sizeof(dx_VertexConstants) / sizeof(float[4])); - mDevice->SetPixelShaderConstantF(0, (float*)&mPixelConstants, sizeof(dx_PixelConstants) / sizeof(float[4])); - mDxUniformsDirty = false; - } -} - -void Renderer9::applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v) -{ - if (targetUniform->psRegisterIndex >= 0) - { - mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount); - } - - if (targetUniform->vsRegisterIndex >= 0) - { - mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount); - } -} - -void Renderer9::applyUniformniv(gl::Uniform *targetUniform, const GLint *v) -{ - ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); - GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; - - for (unsigned int i = 0; i < targetUniform->registerCount; i++) - { - vector[i][0] = (GLfloat)v[4 * i + 0]; - vector[i][1] = (GLfloat)v[4 * i + 1]; - vector[i][2] = (GLfloat)v[4 * i + 2]; - vector[i][3] = (GLfloat)v[4 * i + 3]; - } - - applyUniformnfv(targetUniform, (GLfloat*)vector); -} - -void Renderer9::applyUniformnbv(gl::Uniform *targetUniform, const GLint *v) -{ - ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); - GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; - - for (unsigned int i = 0; i < targetUniform->registerCount; i++) - { - vector[i][0] = (v[4 * i + 0] == GL_FALSE) ? 0.0f : 1.0f; - vector[i][1] = (v[4 * i + 1] == GL_FALSE) ? 0.0f : 1.0f; - vector[i][2] = (v[4 * i + 2] == GL_FALSE) ? 0.0f : 1.0f; - vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f; - } - - applyUniformnfv(targetUniform, (GLfloat*)vector); -} - -void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) -{ - D3DCOLOR color = D3DCOLOR_ARGB(gl::unorm<8>(clearParams.colorClearValue.alpha), - gl::unorm<8>(clearParams.colorClearValue.red), - gl::unorm<8>(clearParams.colorClearValue.green), - gl::unorm<8>(clearParams.colorClearValue.blue)); - float depth = gl::clamp01(clearParams.depthClearValue); - int stencil = clearParams.stencilClearValue & 0x000000FF; - - unsigned int stencilUnmasked = 0x0; - if ((clearParams.mask & GL_STENCIL_BUFFER_BIT) && frameBuffer->hasStencil()) - { - unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat()); - stencilUnmasked = (0x1 << stencilSize) - 1; - } - - bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha; - - const bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) && - (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; - const bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) && - !(clearParams.colorMaskRed && clearParams.colorMaskGreen && - clearParams.colorMaskBlue && alphaUnmasked); - - if (needMaskedColorClear || needMaskedStencilClear) - { - // State which is altered in all paths from this point to the clear call is saved. - // State which is altered in only some paths will be flagged dirty in the case that - // that path is taken. - HRESULT hr; - if (mMaskedClearSavedState == NULL) - { - hr = mDevice->BeginStateBlock(); - ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); - - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); - mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); - mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); - mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - mDevice->SetPixelShader(NULL); - mDevice->SetVertexShader(NULL); - mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); - mDevice->SetStreamSource(0, NULL, 0, 0); - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); - mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); - mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); - mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); - mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); - - for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mDevice->SetStreamSourceFreq(i, 1); - } - - hr = mDevice->EndStateBlock(&mMaskedClearSavedState); - ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); - } - - ASSERT(mMaskedClearSavedState != NULL); - - if (mMaskedClearSavedState != NULL) - { - hr = mMaskedClearSavedState->Capture(); - ASSERT(SUCCEEDED(hr)); - } - - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); - mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); - mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - - if (clearParams.mask & GL_COLOR_BUFFER_BIT) - { - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, - gl_d3d9::ConvertColorMask(clearParams.colorMaskRed, - clearParams.colorMaskGreen, - clearParams.colorMaskBlue, - clearParams.colorMaskAlpha)); - } - else - { - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); - } - - if (stencilUnmasked != 0x0 && (clearParams.mask & GL_STENCIL_BUFFER_BIT)) - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); - mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE); - mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); - mDevice->SetRenderState(D3DRS_STENCILREF, stencil); - mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, clearParams.stencilWriteMask); - mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE); - mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE); - mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); - } - else - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - } - - mDevice->SetPixelShader(NULL); - mDevice->SetVertexShader(NULL); - mDevice->SetFVF(D3DFVF_XYZRHW); - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); - mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); - mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); - mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); - mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); - - for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mDevice->SetStreamSourceFreq(i, 1); - } - - float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges - quad[0][0] = -0.5f; - quad[0][1] = mRenderTargetDesc.height - 0.5f; - quad[0][2] = 0.0f; - quad[0][3] = 1.0f; - - quad[1][0] = mRenderTargetDesc.width - 0.5f; - quad[1][1] = mRenderTargetDesc.height - 0.5f; - quad[1][2] = 0.0f; - quad[1][3] = 1.0f; - - quad[2][0] = -0.5f; - quad[2][1] = -0.5f; - quad[2][2] = 0.0f; - quad[2][3] = 1.0f; - - quad[3][0] = mRenderTargetDesc.width - 0.5f; - quad[3][1] = -0.5f; - quad[3][2] = 0.0f; - quad[3][3] = 1.0f; - - startScene(); - mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4])); - - if (clearParams.mask & GL_DEPTH_BUFFER_BIT) - { - mDevice->SetRenderState(D3DRS_ZENABLE, TRUE); - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); - mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil); - } - - if (mMaskedClearSavedState != NULL) - { - mMaskedClearSavedState->Apply(); - } - } - else if (clearParams.mask) - { - DWORD dxClearFlags = 0; - if (clearParams.mask & GL_COLOR_BUFFER_BIT) - { - dxClearFlags |= D3DCLEAR_TARGET; - } - if (clearParams.mask & GL_DEPTH_BUFFER_BIT) - { - dxClearFlags |= D3DCLEAR_ZBUFFER; - } - if (clearParams.mask & GL_STENCIL_BUFFER_BIT) - { - dxClearFlags |= D3DCLEAR_STENCIL; - } - - mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil); - } -} - -void Renderer9::markAllStateDirty() -{ - mAppliedRenderTargetSerial = 0; - mAppliedDepthbufferSerial = 0; - mAppliedStencilbufferSerial = 0; - mDepthStencilInitialized = false; - mRenderTargetDescInitialized = false; - - mForceSetDepthStencilState = true; - mForceSetRasterState = true; - mForceSetScissor = true; - mForceSetViewport = true; - mForceSetBlendState = true; - - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) - { - mForceSetVertexSamplerStates[i] = true; - mCurVertexTextureSerials[i] = 0; - } - for (unsigned int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++) - { - mForceSetPixelSamplerStates[i] = true; - mCurPixelTextureSerials[i] = 0; - } - - mAppliedIBSerial = 0; - mAppliedProgramBinarySerial = 0; - mDxUniformsDirty = true; - - mVertexDeclarationCache.markStateDirty(); -} - -void Renderer9::releaseDeviceResources() -{ - while (!mEventQueryPool.empty()) - { - mEventQueryPool.back()->Release(); - mEventQueryPool.pop_back(); - } - - if (mMaskedClearSavedState) - { - mMaskedClearSavedState->Release(); - mMaskedClearSavedState = NULL; - } - - mVertexShaderCache.clear(); - mPixelShaderCache.clear(); - - delete mBlit; - mBlit = NULL; - - delete mVertexDataManager; - mVertexDataManager = NULL; - - delete mIndexDataManager; - mIndexDataManager = NULL; - - delete mLineLoopIB; - mLineLoopIB = NULL; - - for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) - { - delete mNullColorbufferCache[i].buffer; - mNullColorbufferCache[i].buffer = NULL; - } - -} - - -void Renderer9::notifyDeviceLost() -{ - mDeviceLost = true; - mDisplay->notifyDeviceLost(); -} - -bool Renderer9::isDeviceLost() -{ - return mDeviceLost; -} - -// set notify to true to broadcast a message to all contexts of the device loss -bool Renderer9::testDeviceLost(bool notify) -{ - HRESULT status = S_OK; - - if (mDeviceEx) - { - status = mDeviceEx->CheckDeviceState(NULL); - } - else if (mDevice) - { - status = mDevice->TestCooperativeLevel(); - } - else - { - // No device yet, so no reset required - } - - bool isLost = FAILED(status) || d3d9::isDeviceLostError(status); - - if (isLost) - { - // ensure we note the device loss -- - // we'll probably get this done again by notifyDeviceLost - // but best to remember it! - // Note that we don't want to clear the device loss status here - // -- this needs to be done by resetDevice - mDeviceLost = true; - if (notify) - { - notifyDeviceLost(); - } - } - - return isLost; -} - -bool Renderer9::testDeviceResettable() -{ - HRESULT status = D3D_OK; - - if (mDeviceEx) - { - status = mDeviceEx->CheckDeviceState(NULL); - } - else if (mDevice) - { - status = mDevice->TestCooperativeLevel(); - } - - // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted - // DEVICEREMOVED indicates the device has been stopped and must be recreated - switch (status) - { - case D3DERR_DEVICENOTRESET: - case D3DERR_DEVICEHUNG: - return true; - case D3DERR_DEVICELOST: - return (mDeviceEx != NULL); - case D3DERR_DEVICEREMOVED: - UNIMPLEMENTED(); - return false; - default: - return false; - } -} - -bool Renderer9::resetDevice() -{ - releaseDeviceResources(); - - D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); - - HRESULT result = D3D_OK; - bool lost = testDeviceLost(false); - int attempts = 3; - - while (lost && attempts > 0) - { - if (mDeviceEx) - { - Sleep(500); // Give the graphics driver some CPU time - result = mDeviceEx->ResetEx(&presentParameters, NULL); - } - else - { - result = mDevice->TestCooperativeLevel(); - while (result == D3DERR_DEVICELOST) - { - Sleep(100); // Give the graphics driver some CPU time - result = mDevice->TestCooperativeLevel(); - } - - if (result == D3DERR_DEVICENOTRESET) - { - result = mDevice->Reset(&presentParameters); - } - } - - lost = testDeviceLost(false); - attempts --; - } - - if (FAILED(result)) - { - ERR("Reset/ResetEx failed multiple times: 0x%08X", result); - return false; - } - - // reset device defaults - initializeDevice(); - mDeviceLost = false; - - return true; -} - -DWORD Renderer9::getAdapterVendor() const -{ - return mAdapterIdentifier.VendorId; -} - -std::string Renderer9::getRendererDescription() const -{ - std::ostringstream rendererString; - - rendererString << mAdapterIdentifier.Description; - if (getShareHandleSupport()) - { - rendererString << " Direct3D9Ex"; - } - else - { - rendererString << " Direct3D9"; - } - - rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion); - rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion); - - return rendererString.str(); -} - -GUID Renderer9::getAdapterIdentifier() const -{ - return mAdapterIdentifier.DeviceIdentifier; -} - -void Renderer9::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray) -{ - for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++) - { - HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format, - TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL); - - multiSampleArray[multiSampleIndex] = SUCCEEDED(result); - } -} - -bool Renderer9::getBGRATextureSupport() const -{ - // DirectX 9 always supports BGRA - return true; -} - -bool Renderer9::getDXT1TextureSupport() -{ - return mDXT1TextureSupport; -} - -bool Renderer9::getDXT3TextureSupport() -{ - return mDXT3TextureSupport; -} - -bool Renderer9::getDXT5TextureSupport() -{ - return mDXT5TextureSupport; -} - -bool Renderer9::getDepthTextureSupport() const -{ - return mDepthTextureSupport; -} - -bool Renderer9::getFloat32TextureSupport(bool *filtering, bool *renderable) -{ - *filtering = mFloat32FilterSupport; - *renderable = mFloat32RenderSupport; - return mFloat32TextureSupport; -} - -bool Renderer9::getFloat16TextureSupport(bool *filtering, bool *renderable) -{ - *filtering = mFloat16FilterSupport; - *renderable = mFloat16RenderSupport; - return mFloat16TextureSupport; -} - -bool Renderer9::getLuminanceTextureSupport() -{ - return mLuminanceTextureSupport; -} - -bool Renderer9::getLuminanceAlphaTextureSupport() -{ - return mLuminanceAlphaTextureSupport; -} - -bool Renderer9::getTextureFilterAnisotropySupport() const -{ - return mSupportsTextureFilterAnisotropy; -} - -float Renderer9::getTextureMaxAnisotropy() const -{ - if (mSupportsTextureFilterAnisotropy) - { - return static_cast(mDeviceCaps.MaxAnisotropy); - } - return 1.0f; -} - -bool Renderer9::getEventQuerySupport() -{ - return mEventQuerySupport; -} - -unsigned int Renderer9::getMaxVertexTextureImageUnits() const -{ - META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); - return mVertexTextureSupport ? MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 : 0; -} - -unsigned int Renderer9::getMaxCombinedTextureImageUnits() const -{ - return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits(); -} - -unsigned int Renderer9::getReservedVertexUniformVectors() const -{ - return 2; // dx_ViewAdjust and dx_DepthRange. -} - -unsigned int Renderer9::getReservedFragmentUniformVectors() const -{ - return 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange. -} - -unsigned int Renderer9::getMaxVertexUniformVectors() const -{ - return MAX_VERTEX_CONSTANT_VECTORS_D3D9 - getReservedVertexUniformVectors(); -} - -unsigned int Renderer9::getMaxFragmentUniformVectors() const -{ - const int maxPixelConstantVectors = (getMajorShaderModel() >= 3) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 : MAX_PIXEL_CONSTANT_VECTORS_SM2; - - return maxPixelConstantVectors - getReservedFragmentUniformVectors(); -} - -unsigned int Renderer9::getMaxVaryingVectors() const -{ - return (getMajorShaderModel() >= 3) ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2; -} - -bool Renderer9::getNonPower2TextureSupport() const -{ - return mSupportsNonPower2Textures; -} - -bool Renderer9::getOcclusionQuerySupport() const -{ - return mOcclusionQuerySupport; -} - -bool Renderer9::getInstancingSupport() const -{ - return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); -} - -bool Renderer9::getShareHandleSupport() const -{ - // PIX doesn't seem to support using share handles, so disable them. - return (mD3d9Ex != NULL) && !gl::perfActive(); -} - -bool Renderer9::getDerivativeInstructionSupport() const -{ - return (mDeviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0; -} - -bool Renderer9::getPostSubBufferSupport() const -{ - return true; -} - -int Renderer9::getMajorShaderModel() const -{ - return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion); -} - -float Renderer9::getMaxPointSize() const -{ - // Point size clamped at 1.0f for SM2 - return getMajorShaderModel() == 3 ? mDeviceCaps.MaxPointSize : 1.0f; -} - -int Renderer9::getMaxViewportDimension() const -{ - int maxTextureDimension = std::min(std::min(getMaxTextureWidth(), getMaxTextureHeight()), - (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE); - return maxTextureDimension; -} - -int Renderer9::getMaxTextureWidth() const -{ - return (int)mDeviceCaps.MaxTextureWidth; -} - -int Renderer9::getMaxTextureHeight() const -{ - return (int)mDeviceCaps.MaxTextureHeight; -} - -bool Renderer9::get32BitIndexSupport() const -{ - return mDeviceCaps.MaxVertexIndex >= (1 << 16); -} - -DWORD Renderer9::getCapsDeclTypes() const -{ - return mDeviceCaps.DeclTypes; -} - -int Renderer9::getMinSwapInterval() const -{ - return mMinSwapInterval; -} - -int Renderer9::getMaxSwapInterval() const -{ - return mMaxSwapInterval; -} - -int Renderer9::getMaxSupportedSamples() const -{ - return mMaxSupportedSamples; -} - -int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const -{ - if (requested == 0) - { - return requested; - } - - std::map::const_iterator itr = mMultiSampleSupport.find(format); - if (itr == mMultiSampleSupport.end()) - { - if (format == D3DFMT_UNKNOWN) - return 0; - return -1; - } - - for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i) - { - if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE) - { - return i; - } - } - - return -1; -} - -unsigned int Renderer9::getMaxRenderTargets() const -{ - // we do not support MRT in d3d9 - return 1; -} - -D3DFORMAT Renderer9::ConvertTextureInternalFormat(GLint internalformat) -{ - switch (internalformat) - { - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT32_OES: - case GL_DEPTH24_STENCIL8_OES: - return D3DFMT_INTZ; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - return D3DFMT_DXT1; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - return D3DFMT_DXT3; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - return D3DFMT_DXT5; - case GL_RGBA32F_EXT: - case GL_RGB32F_EXT: - case GL_ALPHA32F_EXT: - case GL_LUMINANCE32F_EXT: - case GL_LUMINANCE_ALPHA32F_EXT: - return D3DFMT_A32B32G32R32F; - case GL_RGBA16F_EXT: - case GL_RGB16F_EXT: - case GL_ALPHA16F_EXT: - case GL_LUMINANCE16F_EXT: - case GL_LUMINANCE_ALPHA16F_EXT: - return D3DFMT_A16B16G16R16F; - case GL_LUMINANCE8_EXT: - if (getLuminanceTextureSupport()) - { - return D3DFMT_L8; - } - break; - case GL_LUMINANCE8_ALPHA8_EXT: - if (getLuminanceAlphaTextureSupport()) - { - return D3DFMT_A8L8; - } - break; - case GL_RGB8_OES: - case GL_RGB565: - return D3DFMT_X8R8G8B8; - } - - return D3DFMT_A8R8G8B8; -} - -bool Renderer9::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) -{ - bool result = false; - - if (source && dest) - { - TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source->getStorageInstance()); - TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest->getStorageInstance()); - - int levels = source9->levelCount(); - for (int i = 0; i < levels; ++i) - { - IDirect3DSurface9 *srcSurf = source9->getSurfaceLevel(i, false); - IDirect3DSurface9 *dstSurf = dest9->getSurfaceLevel(i, false); - - result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); - - if (srcSurf) srcSurf->Release(); - if (dstSurf) dstSurf->Release(); - - if (!result) - return false; - } - } - - return result; -} - -bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) -{ - bool result = false; - - if (source && dest) - { - TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source->getStorageInstance()); - TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest->getStorageInstance()); - int levels = source9->levelCount(); - for (int f = 0; f < 6; f++) - { - for (int i = 0; i < levels; i++) - { - IDirect3DSurface9 *srcSurf = source9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false); - IDirect3DSurface9 *dstSurf = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true); - - result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); - - if (srcSurf) srcSurf->Release(); - if (dstSurf) dstSurf->Release(); - - if (!result) - return false; - } - } - } - - return result; -} - -D3DPOOL Renderer9::getBufferPool(DWORD usage) const -{ - if (mD3d9Ex != NULL) - { - return D3DPOOL_DEFAULT; - } - else - { - if (!(usage & D3DUSAGE_DYNAMIC)) - { - return D3DPOOL_MANAGED; - } - } - - return D3DPOOL_DEFAULT; -} - -bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) -{ - RECT rect; - rect.left = sourceRect.x; - rect.top = sourceRect.y; - rect.right = sourceRect.x + sourceRect.width; - rect.bottom = sourceRect.y + sourceRect.height; - - return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, level); -} - -bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) -{ - RECT rect; - rect.left = sourceRect.x; - rect.top = sourceRect.y; - rect.right = sourceRect.x + sourceRect.width; - rect.bottom = sourceRect.y + sourceRect.height; - - return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level); -} - -bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect, - bool blitRenderTarget, bool blitDepthStencil) -{ - endScene(); - - if (blitRenderTarget) - { - gl::Renderbuffer *readBuffer = readFramebuffer->getColorbuffer(0); - gl::Renderbuffer *drawBuffer = drawFramebuffer->getColorbuffer(0); - RenderTarget9 *readRenderTarget = NULL; - RenderTarget9 *drawRenderTarget = NULL; - IDirect3DSurface9* readSurface = NULL; - IDirect3DSurface9* drawSurface = NULL; - - if (readBuffer) - { - readRenderTarget = RenderTarget9::makeRenderTarget9(readBuffer->getRenderTarget()); - } - if (drawBuffer) - { - drawRenderTarget = RenderTarget9::makeRenderTarget9(drawBuffer->getRenderTarget()); - } - - if (readRenderTarget) - { - readSurface = readRenderTarget->getSurface(); - } - if (drawRenderTarget) - { - drawSurface = drawRenderTarget->getSurface(); - } - - if (!readSurface || !drawSurface) - { - ERR("Failed to retrieve the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RECT srcRect; - srcRect.left = readRect.x; - srcRect.right = readRect.x + readRect.width; - srcRect.top = readRect.y; - srcRect.bottom = readRect.y + readRect.height; - - RECT dstRect; - dstRect.left = drawRect.x; - dstRect.right = drawRect.x + drawRect.width; - dstRect.top = drawRect.y; - dstRect.bottom = drawRect.y + drawRect.height; - - HRESULT result = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE); - - readSurface->Release(); - drawSurface->Release(); - - if (FAILED(result)) - { - ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); - return false; - } - } - - if (blitDepthStencil) - { - gl::Renderbuffer *readBuffer = readFramebuffer->getDepthOrStencilbuffer(); - gl::Renderbuffer *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer(); - RenderTarget9 *readDepthStencil = NULL; - RenderTarget9 *drawDepthStencil = NULL; - IDirect3DSurface9* readSurface = NULL; - IDirect3DSurface9* drawSurface = NULL; - - if (readBuffer) - { - readDepthStencil = RenderTarget9::makeRenderTarget9(readBuffer->getDepthStencil()); - } - if (drawBuffer) - { - drawDepthStencil = RenderTarget9::makeRenderTarget9(drawBuffer->getDepthStencil()); - } - - if (readDepthStencil) - { - readSurface = readDepthStencil->getSurface(); - } - if (drawDepthStencil) - { - drawSurface = drawDepthStencil->getSurface(); - } - - if (!readSurface || !drawSurface) - { - ERR("Failed to retrieve the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE); - - readSurface->Release(); - drawSurface->Release(); - - if (FAILED(result)) - { - ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); - return false; - } - } - - return true; -} - -void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) -{ - RenderTarget9 *renderTarget = NULL; - IDirect3DSurface9 *surface = NULL; - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); - - if (colorbuffer) - { - renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); - } - - if (renderTarget) - { - surface = renderTarget->getSurface(); - } - - if (!surface) - { - // context must be lost - return; - } - - D3DSURFACE_DESC desc; - surface->GetDesc(&desc); - - if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) - { - UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target - surface->Release(); - return gl::error(GL_OUT_OF_MEMORY); - } - - HRESULT result; - IDirect3DSurface9 *systemSurface = NULL; - bool directToPixels = !packReverseRowOrder && packAlignment <= 4 && getShareHandleSupport() && - x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height && - desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE; - if (directToPixels) - { - // Use the pixels ptr as a shared handle to write directly into client's memory - result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, - D3DPOOL_SYSTEMMEM, &systemSurface, &pixels); - if (FAILED(result)) - { - // Try again without the shared handle - directToPixels = false; - } - } - - if (!directToPixels) - { - result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, - D3DPOOL_SYSTEMMEM, &systemSurface, NULL); - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - surface->Release(); - return gl::error(GL_OUT_OF_MEMORY); - } - } - - result = mDevice->GetRenderTargetData(surface, systemSurface); - surface->Release(); - surface = NULL; - - if (FAILED(result)) - { - systemSurface->Release(); - - // It turns out that D3D will sometimes produce more error - // codes than those documented. - if (d3d9::isDeviceLostError(result)) - { - notifyDeviceLost(); - return gl::error(GL_OUT_OF_MEMORY); - } - else - { - UNREACHABLE(); - return; - } - - } - - if (directToPixels) - { - systemSurface->Release(); - return; - } - - RECT rect; - rect.left = gl::clamp(x, 0L, static_cast(desc.Width)); - rect.top = gl::clamp(y, 0L, static_cast(desc.Height)); - rect.right = gl::clamp(x + width, 0L, static_cast(desc.Width)); - rect.bottom = gl::clamp(y + height, 0L, static_cast(desc.Height)); - - D3DLOCKED_RECT lock; - result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY); - - if (FAILED(result)) - { - UNREACHABLE(); - systemSurface->Release(); - - return; // No sensible error to generate - } - - unsigned char *dest = (unsigned char*)pixels; - unsigned short *dest16 = (unsigned short*)pixels; - - unsigned char *source; - int inputPitch; - if (packReverseRowOrder) - { - source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); - inputPitch = -lock.Pitch; - } - else - { - source = (unsigned char*)lock.pBits; - inputPitch = lock.Pitch; - } - - unsigned int fastPixelSize = 0; - - if (desc.Format == D3DFMT_A8R8G8B8 && - format == GL_BGRA_EXT && - type == GL_UNSIGNED_BYTE) - { - fastPixelSize = 4; - } - else if ((desc.Format == D3DFMT_A4R4G4B4 && - format == GL_BGRA_EXT && - type == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT) || - (desc.Format == D3DFMT_A1R5G5B5 && - format == GL_BGRA_EXT && - type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT)) - { - fastPixelSize = 2; - } - else if (desc.Format == D3DFMT_A16B16G16R16F && - format == GL_RGBA && - type == GL_HALF_FLOAT_OES) - { - fastPixelSize = 8; - } - else if (desc.Format == D3DFMT_A32B32G32R32F && - format == GL_RGBA && - type == GL_FLOAT) - { - fastPixelSize = 16; - } - - for (int j = 0; j < rect.bottom - rect.top; j++) - { - if (fastPixelSize != 0) - { - // Fast path for formats which require no translation: - // D3DFMT_A8R8G8B8 to BGRA/UNSIGNED_BYTE - // D3DFMT_A4R4G4B4 to BGRA/UNSIGNED_SHORT_4_4_4_4_REV_EXT - // D3DFMT_A1R5G5B5 to BGRA/UNSIGNED_SHORT_1_5_5_5_REV_EXT - // D3DFMT_A16B16G16R16F to RGBA/HALF_FLOAT_OES - // D3DFMT_A32B32G32R32F to RGBA/FLOAT - // - // Note that buffers with no alpha go through the slow path below. - memcpy(dest + j * outputPitch, - source + j * inputPitch, - (rect.right - rect.left) * fastPixelSize); - continue; - } - else if (desc.Format == D3DFMT_A8R8G8B8 && - format == GL_RGBA && - type == GL_UNSIGNED_BYTE) - { - // Fast path for swapping red with blue - for (int i = 0; i < rect.right - rect.left; i++) - { - unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); - *(unsigned int*)(dest + 4 * i + j * outputPitch) = - (argb & 0xFF00FF00) | // Keep alpha and green - (argb & 0x00FF0000) >> 16 | // Move red to blue - (argb & 0x000000FF) << 16; // Move blue to red - } - continue; - } - - for (int i = 0; i < rect.right - rect.left; i++) - { - float r; - float g; - float b; - float a; - - switch (desc.Format) - { - case D3DFMT_R5G6B5: - { - unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch); - - a = 1.0f; - b = (rgb & 0x001F) * (1.0f / 0x001F); - g = (rgb & 0x07E0) * (1.0f / 0x07E0); - r = (rgb & 0xF800) * (1.0f / 0xF800); - } - break; - case D3DFMT_A1R5G5B5: - { - unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch); - - a = (argb & 0x8000) ? 1.0f : 0.0f; - b = (argb & 0x001F) * (1.0f / 0x001F); - g = (argb & 0x03E0) * (1.0f / 0x03E0); - r = (argb & 0x7C00) * (1.0f / 0x7C00); - } - break; - case D3DFMT_A8R8G8B8: - { - unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); - - a = (argb & 0xFF000000) * (1.0f / 0xFF000000); - b = (argb & 0x000000FF) * (1.0f / 0x000000FF); - g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00); - r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000); - } - break; - case D3DFMT_X8R8G8B8: - { - unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch); - - a = 1.0f; - b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF); - g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00); - r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000); - } - break; - case D3DFMT_A2R10G10B10: - { - unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); - - a = (argb & 0xC0000000) * (1.0f / 0xC0000000); - b = (argb & 0x000003FF) * (1.0f / 0x000003FF); - g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00); - r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000); - } - break; - case D3DFMT_A32B32G32R32F: - { - // float formats in D3D are stored rgba, rather than the other way round - r = *((float*)(source + 16 * i + j * inputPitch) + 0); - g = *((float*)(source + 16 * i + j * inputPitch) + 1); - b = *((float*)(source + 16 * i + j * inputPitch) + 2); - a = *((float*)(source + 16 * i + j * inputPitch) + 3); - } - break; - case D3DFMT_A16B16G16R16F: - { - // float formats in D3D are stored rgba, rather than the other way round - r = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 0)); - g = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 1)); - b = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 2)); - a = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 3)); - } - break; - default: - UNIMPLEMENTED(); // FIXME - UNREACHABLE(); - return; - } - - switch (format) - { - case GL_RGBA: - switch (type) - { - case GL_UNSIGNED_BYTE: - dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f); - dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); - dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f); - dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); - break; - default: UNREACHABLE(); - } - break; - case GL_BGRA_EXT: - switch (type) - { - case GL_UNSIGNED_BYTE: - dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f); - dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); - dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f); - dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); - break; - case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - dest16[i + j * outputPitch / sizeof(unsigned short)] = - ((unsigned short)(15 * a + 0.5f) << 12)| - ((unsigned short)(15 * r + 0.5f) << 8) | - ((unsigned short)(15 * g + 0.5f) << 4) | - ((unsigned short)(15 * b + 0.5f) << 0); - break; - case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - dest16[i + j * outputPitch / sizeof(unsigned short)] = - ((unsigned short)( a + 0.5f) << 15) | - ((unsigned short)(31 * r + 0.5f) << 10) | - ((unsigned short)(31 * g + 0.5f) << 5) | - ((unsigned short)(31 * b + 0.5f) << 0); - break; - default: UNREACHABLE(); - } - break; - case GL_RGB: - switch (type) - { - case GL_UNSIGNED_SHORT_5_6_5: - dest16[i + j * outputPitch / sizeof(unsigned short)] = - ((unsigned short)(31 * b + 0.5f) << 0) | - ((unsigned short)(63 * g + 0.5f) << 5) | - ((unsigned short)(31 * r + 0.5f) << 11); - break; - case GL_UNSIGNED_BYTE: - dest[3 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f); - dest[3 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); - dest[3 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f); - break; - default: UNREACHABLE(); - } - break; - default: UNREACHABLE(); - } - } - } - - systemSurface->UnlockRect(); - - systemSurface->Release(); -} - -RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth) -{ - SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); - IDirect3DSurface9 *surface = NULL; - if (depth) - { - surface = swapChain9->getDepthStencil(); - } - else - { - surface = swapChain9->getRenderTarget(); - } - - RenderTarget9 *renderTarget = new RenderTarget9(this, surface); - - return renderTarget; -} - -RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) -{ - RenderTarget9 *renderTarget = new RenderTarget9(this, width, height, format, samples); - return renderTarget; -} - -ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type) -{ - ShaderExecutable9 *executable = NULL; - - switch (type) - { - case rx::SHADER_VERTEX: - { - IDirect3DVertexShader9 *vshader = createVertexShader((DWORD*)function, length); - if (vshader) - { - executable = new ShaderExecutable9(function, length, vshader); - } - } - break; - case rx::SHADER_PIXEL: - { - IDirect3DPixelShader9 *pshader = createPixelShader((DWORD*)function, length); - if (pshader) - { - executable = new ShaderExecutable9(function, length, pshader); - } - } - break; - default: - UNREACHABLE(); - break; - } - - return executable; -} - -ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type) -{ - const char *profile = NULL; - - switch (type) - { - case rx::SHADER_VERTEX: - profile = getMajorShaderModel() >= 3 ? "vs_3_0" : "vs_2_0"; - break; - case rx::SHADER_PIXEL: - profile = getMajorShaderModel() >= 3 ? "ps_3_0" : "ps_2_0"; - break; - default: - UNREACHABLE(); - return NULL; - } - - ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, ANGLE_COMPILE_OPTIMIZATION_LEVEL, true); - if (!binary) - return NULL; - - ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type); - binary->Release(); - - return executable; -} - -bool Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) -{ - return mBlit->boxFilter(source, dest); -} - -D3DPOOL Renderer9::getTexturePool(DWORD usage) const -{ - if (mD3d9Ex != NULL) - { - return D3DPOOL_DEFAULT; - } - else - { - if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET))) - { - return D3DPOOL_MANAGED; - } - } - - return D3DPOOL_DEFAULT; -} - -bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged) -{ - if (source && dest) - { - HRESULT result = D3DERR_OUTOFVIDEOMEMORY; - - if (fromManaged) - { - D3DSURFACE_DESC desc; - source->GetDesc(&desc); - - IDirect3DSurface9 *surf = 0; - result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); - - if (SUCCEEDED(result)) - { - Image9::copyLockableSurfaces(surf, source); - result = mDevice->UpdateSurface(surf, NULL, dest, NULL); - surf->Release(); - } - } - else - { - endScene(); - result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE); - } - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return false; - } - } - - return true; -} - -Image *Renderer9::createImage() -{ - return new Image9(); -} - -void Renderer9::generateMipmap(Image *dest, Image *src) -{ - Image9 *src9 = Image9::makeImage9(src); - Image9 *dst9 = Image9::makeImage9(dest); - Image9::generateMipmap(dst9, src9); -} - -TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain) -{ - SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); - return new TextureStorage9_2D(this, swapChain9); -} - -TextureStorage *Renderer9::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) -{ - return new TextureStorage9_2D(this, levels, internalformat, usage, forceRenderable, width, height); -} - -TextureStorage *Renderer9::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) -{ - return new TextureStorage9_Cube(this, levels, internalformat, usage, forceRenderable, size); -} - -bool Renderer9::getLUID(LUID *adapterLuid) const -{ - adapterLuid->HighPart = 0; - adapterLuid->LowPart = 0; - - if (mD3d9Ex) - { - mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid); - return true; - } - - return false; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h deleted file mode 100644 index f8932c4fd4..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h +++ /dev/null @@ -1,350 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Renderer9.h: Defines a back-end specific class for the D3D9 renderer. - -#ifndef LIBGLESV2_RENDERER_RENDERER9_H_ -#define LIBGLESV2_RENDERER_RENDERER9_H_ - -#include "common/angleutils.h" -#include "libGLESv2/mathutil.h" -#include "libGLESv2/renderer/ShaderCache.h" -#include "libGLESv2/renderer/VertexDeclarationCache.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/RenderTarget.h" - -namespace gl -{ -class Renderbuffer; -} - -namespace rx -{ -class VertexDataManager; -class IndexDataManager; -class StreamingIndexBufferInterface; -struct TranslatedAttribute; - -class Renderer9 : public Renderer -{ - public: - Renderer9(egl::Display *display, HDC hDc, bool softwareDevice); - virtual ~Renderer9(); - - static Renderer9 *makeRenderer9(Renderer *renderer); - - virtual EGLint initialize(); - virtual bool resetDevice(); - - virtual int generateConfigs(ConfigDesc **configDescList); - virtual void deleteConfigs(ConfigDesc *configDescList); - - void startScene(); - void endScene(); - - virtual void sync(bool block); - - virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); - - IDirect3DQuery9* allocateEventQuery(); - void freeEventQuery(IDirect3DQuery9* query); - - // resource creation - IDirect3DVertexShader9 *createVertexShader(const DWORD *function, size_t length); - IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length); - HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer); - HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer); -#if 0 - void *createTexture2D(); - void *createTextureCube(); - void *createQuery(); - void *createIndexBuffer(); - void *createVertexbuffer(); - - // state setup - void applyShaders(); - void applyConstants(); -#endif - virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); - virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture); - - virtual void setRasterizerState(const gl::RasterizerState &rasterState); - virtual void setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, - unsigned int sampleMask); - virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW); - - virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); - virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport); - - virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer); - virtual void applyShaders(gl::ProgramBinary *programBinary); - virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray); - virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount); - virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances); - virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); - - virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances); - virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); - - virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); - - virtual void markAllStateDirty(); - - // lost device - void notifyDeviceLost(); - virtual bool isDeviceLost(); - virtual bool testDeviceLost(bool notify); - virtual bool testDeviceResettable(); - - // Renderer capabilities - IDirect3DDevice9 *getDevice() { return mDevice; } - virtual DWORD getAdapterVendor() const; - virtual std::string getRendererDescription() const; - virtual GUID getAdapterIdentifier() const; - - virtual bool getBGRATextureSupport() const; - virtual bool getDXT1TextureSupport(); - virtual bool getDXT3TextureSupport(); - virtual bool getDXT5TextureSupport(); - virtual bool getEventQuerySupport(); - virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable); - virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable); - virtual bool getLuminanceTextureSupport(); - virtual bool getLuminanceAlphaTextureSupport(); - virtual unsigned int getMaxVertexTextureImageUnits() const; - virtual unsigned int getMaxCombinedTextureImageUnits() const; - virtual unsigned int getReservedVertexUniformVectors() const; - virtual unsigned int getReservedFragmentUniformVectors() const; - virtual unsigned int getMaxVertexUniformVectors() const; - virtual unsigned int getMaxFragmentUniformVectors() const; - virtual unsigned int getMaxVaryingVectors() const; - virtual bool getNonPower2TextureSupport() const; - virtual bool getDepthTextureSupport() const; - virtual bool getOcclusionQuerySupport() const; - virtual bool getInstancingSupport() const; - virtual bool getTextureFilterAnisotropySupport() const; - virtual float getTextureMaxAnisotropy() const; - virtual bool getShareHandleSupport() const; - virtual bool getDerivativeInstructionSupport() const; - virtual bool getPostSubBufferSupport() const; - - virtual int getMajorShaderModel() const; - virtual float getMaxPointSize() const; - virtual int getMaxViewportDimension() const; - virtual int getMaxTextureWidth() const; - virtual int getMaxTextureHeight() const; - virtual bool get32BitIndexSupport() const; - DWORD getCapsDeclTypes() const; - virtual int getMinSwapInterval() const; - virtual int getMaxSwapInterval() const; - - virtual GLsizei getMaxSupportedSamples() const; - int getNearestSupportedSamples(D3DFORMAT format, int requested) const; - - virtual unsigned int getMaxRenderTargets() const; - - D3DFORMAT ConvertTextureInternalFormat(GLint internalformat); - - // Pixel operations - virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source); - virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source); - - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level); - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level); - - virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - bool blitRenderTarget, bool blitDepthStencil); - virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels); - - // RenderTarget creation - virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); - virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth); - - // Shader operations - virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type); - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type); - - // Image operations - virtual Image *createImage(); - virtual void generateMipmap(Image *dest, Image *source); - virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); - virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); - virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); - - // Buffer creation - virtual VertexBuffer *createVertexBuffer(); - virtual IndexBuffer *createIndexBuffer(); - virtual BufferStorage *createBufferStorage(); - - // Query and Fence creation - virtual QueryImpl *createQuery(GLenum type); - virtual FenceImpl *createFence(); - - // D3D9-renderer specific methods - bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); - - D3DPOOL getTexturePool(DWORD usage) const; - - virtual bool getLUID(LUID *adapterLuid) const; - - private: - DISALLOW_COPY_AND_ASSIGN(Renderer9); - - void applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v); - void applyUniformniv(gl::Uniform *targetUniform, const GLint *v); - void applyUniformnbv(gl::Uniform *targetUniform, const GLint *v); - - void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); - void drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer); - - void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray); - bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); - gl::Renderbuffer *getNullColorbuffer(gl::Renderbuffer *depthbuffer); - - D3DPOOL getBufferPool(DWORD usage) const; - - HMODULE mD3d9Module; - HDC mDc; - - void initializeDevice(); - D3DPRESENT_PARAMETERS getDefaultPresentParameters(); - void releaseDeviceResources(); - - UINT mAdapter; - D3DDEVTYPE mDeviceType; - bool mSoftwareDevice; // FIXME: Deprecate - IDirect3D9 *mD3d9; // Always valid after successful initialization. - IDirect3D9Ex *mD3d9Ex; // Might be null if D3D9Ex is not supported. - IDirect3DDevice9 *mDevice; - IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported. - - Blit *mBlit; - - HWND mDeviceWindow; - - bool mDeviceLost; - D3DCAPS9 mDeviceCaps; - D3DADAPTER_IDENTIFIER9 mAdapterIdentifier; - - D3DPRIMITIVETYPE mPrimitiveType; - int mPrimitiveCount; - GLsizei mRepeatDraw; - - bool mSceneStarted; - bool mSupportsNonPower2Textures; - bool mSupportsTextureFilterAnisotropy; - int mMinSwapInterval; - int mMaxSwapInterval; - - bool mOcclusionQuerySupport; - bool mEventQuerySupport; - bool mVertexTextureSupport; - - bool mDepthTextureSupport; - - bool mFloat32TextureSupport; - bool mFloat32FilterSupport; - bool mFloat32RenderSupport; - - bool mFloat16TextureSupport; - bool mFloat16FilterSupport; - bool mFloat16RenderSupport; - - bool mDXT1TextureSupport; - bool mDXT3TextureSupport; - bool mDXT5TextureSupport; - - bool mLuminanceTextureSupport; - bool mLuminanceAlphaTextureSupport; - - std::map mMultiSampleSupport; - GLsizei mMaxSupportedSamples; - - // current render target states - unsigned int mAppliedRenderTargetSerial; - unsigned int mAppliedDepthbufferSerial; - unsigned int mAppliedStencilbufferSerial; - bool mDepthStencilInitialized; - bool mRenderTargetDescInitialized; - rx::RenderTarget::Desc mRenderTargetDesc; - unsigned int mCurStencilSize; - unsigned int mCurDepthSize; - - IDirect3DStateBlock9 *mMaskedClearSavedState; - - // previously set render states - bool mForceSetDepthStencilState; - gl::DepthStencilState mCurDepthStencilState; - int mCurStencilRef; - int mCurStencilBackRef; - bool mCurFrontFaceCCW; - - bool mForceSetRasterState; - gl::RasterizerState mCurRasterState; - - bool mForceSetScissor; - gl::Rectangle mCurScissor; - bool mScissorEnabled; - - bool mForceSetViewport; - gl::Rectangle mCurViewport; - float mCurNear; - float mCurFar; - float mCurDepthFront; - - bool mForceSetBlendState; - gl::BlendState mCurBlendState; - gl::Color mCurBlendColor; - GLuint mCurSampleMask; - - // Currently applied sampler states - bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - gl::SamplerState mCurVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - - bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; - gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; - - // Currently applied textures - unsigned int mCurVertexTextureSerials[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS]; - - unsigned int mAppliedIBSerial; - unsigned int mAppliedProgramBinarySerial; - - rx::dx_VertexConstants mVertexConstants; - rx::dx_PixelConstants mPixelConstants; - bool mDxUniformsDirty; - - // A pool of event queries that are currently unused. - std::vector mEventQueryPool; - VertexShaderCache mVertexShaderCache; - PixelShaderCache mPixelShaderCache; - - VertexDataManager *mVertexDataManager; - VertexDeclarationCache mVertexDeclarationCache; - - IndexDataManager *mIndexDataManager; - StreamingIndexBufferInterface *mLineLoopIB; - - enum { NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12 }; - struct NullColorbufferCacheEntry - { - UINT lruCount; - int width; - int height; - gl::Renderbuffer *buffer; - } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES]; - UINT mMaxNullColorbufferLRU; - -}; - -} -#endif // LIBGLESV2_RENDERER_RENDERER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable11.cpp deleted file mode 100644 index e1eb560334..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable11.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader -// executable implementation details. - -#include "libGLESv2/renderer/ShaderExecutable11.h" - -#include "common/debug.h" - -namespace rx -{ - -ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable) - : ShaderExecutable(function, length) -{ - mPixelExecutable = executable; - mVertexExecutable = NULL; - mGeometryExecutable = NULL; - - mConstantBuffer = NULL; -} - -ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable) - : ShaderExecutable(function, length) -{ - mVertexExecutable = executable; - mPixelExecutable = NULL; - mGeometryExecutable = NULL; - - mConstantBuffer = NULL; -} - -ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable) - : ShaderExecutable(function, length) -{ - mGeometryExecutable = executable; - mVertexExecutable = NULL; - mPixelExecutable = NULL; - - mConstantBuffer = NULL; -} - -ShaderExecutable11::~ShaderExecutable11() -{ - if (mVertexExecutable) - { - mVertexExecutable->Release(); - } - if (mPixelExecutable) - { - mPixelExecutable->Release(); - } - if (mGeometryExecutable) - { - mGeometryExecutable->Release(); - } - - if (mConstantBuffer) - { - mConstantBuffer->Release(); - } -} - -ShaderExecutable11 *ShaderExecutable11::makeShaderExecutable11(ShaderExecutable *executable) -{ - ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable11*, executable)); - return static_cast(executable); -} - -ID3D11VertexShader *ShaderExecutable11::getVertexShader() const -{ - return mVertexExecutable; -} - -ID3D11PixelShader *ShaderExecutable11::getPixelShader() const -{ - return mPixelExecutable; -} - -ID3D11GeometryShader *ShaderExecutable11::getGeometryShader() const -{ - return mGeometryExecutable; -} - -ID3D11Buffer *ShaderExecutable11::getConstantBuffer(ID3D11Device *device, unsigned int registerCount) -{ - if (!mConstantBuffer && registerCount > 0) - { - D3D11_BUFFER_DESC constantBufferDescription = {0}; - constantBufferDescription.ByteWidth = registerCount * sizeof(float[4]); - constantBufferDescription.Usage = D3D11_USAGE_DYNAMIC; - constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - constantBufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - constantBufferDescription.MiscFlags = 0; - constantBufferDescription.StructureByteStride = 0; - - HRESULT result = device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer); - ASSERT(SUCCEEDED(result)); - } - - return mConstantBuffer; -} - -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable11.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable11.h deleted file mode 100644 index c6ec1cf7d2..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable11.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ShaderExecutable11.h: Defines a D3D11-specific class to contain shader -// executable implementation details. - -#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ -#define LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ - -#include "libGLESv2/renderer/ShaderExecutable.h" - -namespace rx -{ - -class ShaderExecutable11 : public ShaderExecutable -{ - public: - ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable); - ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable); - ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable); - - virtual ~ShaderExecutable11(); - - static ShaderExecutable11 *makeShaderExecutable11(ShaderExecutable *executable); - - ID3D11PixelShader *getPixelShader() const; - ID3D11VertexShader *getVertexShader() const; - ID3D11GeometryShader *getGeometryShader() const; - - ID3D11Buffer *getConstantBuffer(ID3D11Device *device, unsigned int registerCount); - - private: - DISALLOW_COPY_AND_ASSIGN(ShaderExecutable11); - - ID3D11PixelShader *mPixelExecutable; - ID3D11VertexShader *mVertexExecutable; - ID3D11GeometryShader *mGeometryExecutable; - - ID3D11Buffer *mConstantBuffer; -}; - -} - -#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable9.cpp deleted file mode 100644 index 98868a3fbf..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable9.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ShaderExecutable9.cpp: Implements a D3D9-specific class to contain shader -// executable implementation details. - -#include "libGLESv2/renderer/ShaderExecutable9.h" - -#include "common/debug.h" - -namespace rx -{ - -ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable) - : ShaderExecutable(function, length) -{ - mPixelExecutable = executable; - mVertexExecutable = NULL; -} - -ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable) - : ShaderExecutable(function, length) -{ - mVertexExecutable = executable; - mPixelExecutable = NULL; -} - -ShaderExecutable9::~ShaderExecutable9() -{ - if (mVertexExecutable) - { - mVertexExecutable->Release(); - } - if (mPixelExecutable) - { - mPixelExecutable->Release(); - } -} - -ShaderExecutable9 *ShaderExecutable9::makeShaderExecutable9(ShaderExecutable *executable) -{ - ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable9*, executable)); - return static_cast(executable); -} - -IDirect3DVertexShader9 *ShaderExecutable9::getVertexShader() const -{ - return mVertexExecutable; -} - -IDirect3DPixelShader9 *ShaderExecutable9::getPixelShader() const -{ - return mPixelExecutable; -} - -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable9.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable9.h deleted file mode 100644 index fa1e6c2844..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable9.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ShaderExecutable9.h: Defines a D3D9-specific class to contain shader -// executable implementation details. - -#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ -#define LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ - -#include "libGLESv2/renderer/ShaderExecutable.h" - -namespace rx -{ - -class ShaderExecutable9 : public ShaderExecutable -{ - public: - ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable); - ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable); - virtual ~ShaderExecutable9(); - - static ShaderExecutable9 *makeShaderExecutable9(ShaderExecutable *executable); - - IDirect3DPixelShader9 *getPixelShader() const; - IDirect3DVertexShader9 *getVertexShader() const; - - private: - DISALLOW_COPY_AND_ASSIGN(ShaderExecutable9); - - IDirect3DPixelShader9 *mPixelExecutable; - IDirect3DVertexShader9 *mVertexExecutable; -}; - -} - -#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h index a6870ebedc..8231fbcb25 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h @@ -1,3 +1,4 @@ +#include "../precompiled.h" // // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -12,6 +13,10 @@ #include "common/angleutils.h" +#if !defined(ANGLE_FORCE_VSYNC_OFF) +#define ANGLE_FORCE_VSYNC_OFF 0 +#endif + namespace rx { @@ -33,7 +38,7 @@ class SwapChain virtual HANDLE getShareHandle() {return mShareHandle;}; protected: - const EGLNativeWindowType mWindow; // Window that the surface is created for. + const EGLNativeWindowType mWindow; // Window that the surface is created for. const GLenum mBackBufferFormat; const GLenum mDepthBufferFormat; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp deleted file mode 100644 index 2fe15ff5b8..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp +++ /dev/null @@ -1,797 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. - -#include "libGLESv2/renderer/SwapChain11.h" - -#include "libGLESv2/renderer/renderer11_utils.h" -#include "libGLESv2/renderer/Renderer11.h" -#include "libGLESv2/renderer/shaders/compiled/passthrough11vs.h" -#include "libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h" - -namespace rx -{ - -SwapChain11::SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat) - : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) -{ - mSwapChain = NULL; - mBackBufferTexture = NULL; - mBackBufferRTView = NULL; - mOffscreenTexture = NULL; - mOffscreenRTView = NULL; - mOffscreenSRView = NULL; - mDepthStencilTexture = NULL; - mDepthStencilDSView = NULL; - mQuadVB = NULL; - mPassThroughSampler = NULL; - mPassThroughIL = NULL; - mPassThroughVS = NULL; - mPassThroughPS = NULL; - mWidth = -1; - mHeight = -1; - mSwapInterval = 0; - mAppCreatedShareHandle = mShareHandle != NULL; - mPassThroughResourcesInit = false; -} - -SwapChain11::~SwapChain11() -{ - release(); -} - -void SwapChain11::release() -{ - if (mSwapChain) - { - mSwapChain->Release(); - mSwapChain = NULL; - } - - if (mBackBufferTexture) - { - mBackBufferTexture->Release(); - mBackBufferTexture = NULL; - } - - if (mBackBufferRTView) - { - mBackBufferRTView->Release(); - mBackBufferRTView = NULL; - } - - if (mOffscreenTexture) - { - mOffscreenTexture->Release(); - mOffscreenTexture = NULL; - } - - if (mOffscreenRTView) - { - mOffscreenRTView->Release(); - mOffscreenRTView = NULL; - } - - if (mOffscreenSRView) - { - mOffscreenSRView->Release(); - mOffscreenSRView = NULL; - } - - if (mDepthStencilTexture) - { - mDepthStencilTexture->Release(); - mDepthStencilTexture = NULL; - } - - if (mDepthStencilDSView) - { - mDepthStencilDSView->Release(); - mDepthStencilDSView = NULL; - } - - if (mQuadVB) - { - mQuadVB->Release(); - mQuadVB = NULL; - } - - if (mPassThroughSampler) - { - mPassThroughSampler->Release(); - mPassThroughSampler = NULL; - } - - if (mPassThroughIL) - { - mPassThroughIL->Release(); - mPassThroughIL = NULL; - } - - if (mPassThroughVS) - { - mPassThroughVS->Release(); - mPassThroughVS = NULL; - } - - if (mPassThroughPS) - { - mPassThroughPS->Release(); - mPassThroughPS = NULL; - } - - if (!mAppCreatedShareHandle) - { - mShareHandle = NULL; - } -} - -void SwapChain11::releaseOffscreenTexture() -{ - if (mOffscreenTexture) - { - mOffscreenTexture->Release(); - mOffscreenTexture = NULL; - } - - if (mOffscreenRTView) - { - mOffscreenRTView->Release(); - mOffscreenRTView = NULL; - } - - if (mOffscreenSRView) - { - mOffscreenSRView->Release(); - mOffscreenSRView = NULL; - } - - if (mDepthStencilTexture) - { - mDepthStencilTexture->Release(); - mDepthStencilTexture = NULL; - } - - if (mDepthStencilDSView) - { - mDepthStencilDSView->Release(); - mDepthStencilDSView = NULL; - } -} - -EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight) -{ - ID3D11Device *device = mRenderer->getDevice(); - - ASSERT(device != NULL); - - // D3D11 does not allow zero size textures - ASSERT(backbufferWidth >= 1); - ASSERT(backbufferHeight >= 1); - - // Preserve the render target content - ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; - if (previousOffscreenTexture) - { - previousOffscreenTexture->AddRef(); - } - const int previousWidth = mWidth; - const int previousHeight = mHeight; - - releaseOffscreenTexture(); - - // If the app passed in a share handle, open the resource - // See EGL_ANGLE_d3d_share_handle_client_buffer - if (mAppCreatedShareHandle) - { - ID3D11Resource *tempResource11; - HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11); - - if (FAILED(result)) - { - ERR("Failed to open the swap chain pbuffer share handle: %08lX", result); - release(); - return EGL_BAD_PARAMETER; - } - - result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture); - tempResource11->Release(); - - if (FAILED(result)) - { - ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result); - release(); - return EGL_BAD_PARAMETER; - } - - // Validate offscreen texture parameters - D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; - mOffscreenTexture->GetDesc(&offscreenTextureDesc); - - if (offscreenTextureDesc.Width != (UINT)backbufferWidth - || offscreenTextureDesc.Height != (UINT)backbufferHeight - || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat) - || offscreenTextureDesc.MipLevels != 1 - || offscreenTextureDesc.ArraySize != 1) - { - ERR("Invalid texture parameters in the shared offscreen texture pbuffer"); - release(); - return EGL_BAD_PARAMETER; - } - } - else - { - const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport(); - - D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; - offscreenTextureDesc.Width = backbufferWidth; - offscreenTextureDesc.Height = backbufferHeight; - offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); - offscreenTextureDesc.MipLevels = 1; - offscreenTextureDesc.ArraySize = 1; - offscreenTextureDesc.SampleDesc.Count = 1; - offscreenTextureDesc.SampleDesc.Quality = 0; - offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT; - offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; - offscreenTextureDesc.CPUAccessFlags = 0; - offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0; - - HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture); - - if (FAILED(result)) - { - ERR("Could not create offscreen texture: %08lX", result); - release(); - - if (d3d11::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } - } - - d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture"); - - // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client - if (useSharedResource) - { - IDXGIResource *offscreenTextureResource = NULL; - result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource); - - // Fall back to no share handle on failure - if (FAILED(result)) - { - ERR("Could not query offscreen texture resource: %08lX", result); - } - else - { - result = offscreenTextureResource->GetSharedHandle(&mShareHandle); - offscreenTextureResource->Release(); - - if (FAILED(result)) - { - mShareHandle = NULL; - ERR("Could not get offscreen texture shared handle: %08lX", result); - } - } - } - } - - HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView); - - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target"); - - result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource"); - - if (mDepthBufferFormat != GL_NONE) - { - D3D11_TEXTURE2D_DESC depthStencilDesc = {0}; - depthStencilDesc.Width = backbufferWidth; - depthStencilDesc.Height = backbufferHeight; - depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat); - depthStencilDesc.MipLevels = 1; - depthStencilDesc.ArraySize = 1; - depthStencilDesc.SampleDesc.Count = 1; - depthStencilDesc.SampleDesc.Quality = 0; - depthStencilDesc.Usage = D3D11_USAGE_DEFAULT; - depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; - depthStencilDesc.CPUAccessFlags = 0; - depthStencilDesc.MiscFlags = 0; - - result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture); - if (FAILED(result)) - { - ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); - release(); - - if (d3d11::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } - } - d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture"); - - result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view"); - } - - mWidth = backbufferWidth; - mHeight = backbufferHeight; - - if (previousOffscreenTexture != NULL) - { - D3D11_BOX sourceBox = {0}; - sourceBox.left = 0; - sourceBox.right = std::min(previousWidth, mWidth); - sourceBox.top = std::max(previousHeight - mHeight, 0); - sourceBox.bottom = previousHeight; - sourceBox.front = 0; - sourceBox.back = 1; - - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - const int yoffset = std::max(mHeight - previousHeight, 0); - deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox); - - previousOffscreenTexture->Release(); - - if (mSwapChain) - { - swapRect(0, 0, mWidth, mHeight); - } - } - - return EGL_SUCCESS; -} - -EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) -{ - ID3D11Device *device = mRenderer->getDevice(); - - if (device == NULL) - { - return EGL_BAD_ACCESS; - } - - if (!mSwapChain) - reset(backbufferWidth, backbufferHeight, mSwapInterval); - - // Can only call resize if we have already created our swap buffer and resources - ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); - - if (mBackBufferTexture) - { - mBackBufferTexture->Release(); - mBackBufferTexture = NULL; - } - - if (mBackBufferRTView) - { - mBackBufferRTView->Release(); - mBackBufferRTView = NULL; - } - - // Resize swap chain - DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); - HRESULT result = mSwapChain->ResizeBuffers(2, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0); - - if (FAILED(result)) - { - ERR("Error resizing swap chain buffers: 0x%08X", result); - release(); - - if (d3d11::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } - } - - result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); - ASSERT(SUCCEEDED(result)); - if (SUCCEEDED(result)) - { - d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); - } - - result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); - ASSERT(SUCCEEDED(result)); - if (SUCCEEDED(result)) - { - d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); - } - - return resetOffscreenTexture(backbufferWidth, backbufferHeight); -} - -EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) -{ - ID3D11Device *device = mRenderer->getDevice(); - - if (device == NULL) - { - return EGL_BAD_ACCESS; - } - - // Release specific resources to free up memory for the new render target, while the - // old render target still exists for the purpose of preserving its contents. - if (mSwapChain) - { - mSwapChain->Release(); - mSwapChain = NULL; - } - - if (mBackBufferTexture) - { - mBackBufferTexture->Release(); - mBackBufferTexture = NULL; - } - - if (mBackBufferRTView) - { - mBackBufferRTView->Release(); - mBackBufferRTView = NULL; - } - - mSwapInterval = static_cast(swapInterval); - if (mSwapInterval > 4) - { - // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range - return EGL_BAD_PARAMETER; - } - - // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains - if (backbufferWidth < 1 || backbufferHeight < 1) - { - releaseOffscreenTexture(); - return EGL_SUCCESS; - } - - if (mWindow) - { -#if !defined(ANGLE_OS_WINRT) - // We cannot create a swap chain for an HWND that is owned by a different process - DWORD currentProcessId = GetCurrentProcessId(); - DWORD wndProcessId; - GetWindowThreadProcessId(mWindow, &wndProcessId); - - if (currentProcessId != wndProcessId) - { - ERR("Could not create swap chain, window owned by different process"); - release(); - return EGL_BAD_NATIVE_WINDOW; - } - - IDXGIFactory *factory = mRenderer->getDxgiFactory(); - - DXGI_SWAP_CHAIN_DESC swapChainDesc = {0}; - swapChainDesc.BufferCount = 2; - swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); - swapChainDesc.BufferDesc.Width = backbufferWidth; - swapChainDesc.BufferDesc.Height = backbufferHeight; - swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; - swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; - swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; - swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; - swapChainDesc.Windowed = TRUE; - swapChainDesc.OutputWindow = mWindow; -#else - IDXGIFactory2 *factory; - HRESULT result = mRenderer->getDxgiFactory()->QueryInterface(IID_PPV_ARGS(&factory)); - ASSERT(SUCCEEDED(result)); - - DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; - swapChainDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); - swapChainDesc.Width = backbufferWidth; - swapChainDesc.Height = backbufferHeight; - swapChainDesc.Stereo = FALSE; -#if !defined(ANGLE_OS_WINPHONE) - swapChainDesc.BufferCount = 2; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; -#else - swapChainDesc.BufferCount = 1; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; -#endif -#endif - - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swapChainDesc.Flags = 0; - swapChainDesc.SampleDesc.Count = 1; - swapChainDesc.SampleDesc.Quality = 0; - -#if !defined(ANGLE_OS_WINRT) - HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); -#else - IDXGISwapChain1 *swapChain; - result = factory->CreateSwapChainForCoreWindow(device, mWindow, &swapChainDesc, NULL, &swapChain); - mSwapChain = swapChain; -#endif - - if (FAILED(result)) - { - ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); - release(); - - if (d3d11::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } - } - - result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); - - result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); - } - - // If we are resizing the swap chain, we don't wish to recreate all the static resources - if (!mPassThroughResourcesInit) - { - mPassThroughResourcesInit = true; - initPassThroughResources(); - } - - return resetOffscreenTexture(backbufferWidth, backbufferHeight); -} - -void SwapChain11::initPassThroughResources() -{ - ID3D11Device *device = mRenderer->getDevice(); - - ASSERT(device != NULL); - - // Make sure our resources are all not allocated, when we create - ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL); - ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL); - - D3D11_BUFFER_DESC vbDesc; - vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; - vbDesc.Usage = D3D11_USAGE_DYNAMIC; - vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - vbDesc.MiscFlags = 0; - vbDesc.StructureByteStride = 0; - - HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer"); - - D3D11_SAMPLER_DESC samplerDesc; - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.MipLODBias = 0.0f; - samplerDesc.MaxAnisotropy = 0; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; - samplerDesc.BorderColor[0] = 0.0f; - samplerDesc.BorderColor[1] = 0.0f; - samplerDesc.BorderColor[2] = 0.0f; - samplerDesc.BorderColor[3] = 0.0f; - samplerDesc.MinLOD = 0; - samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; - - result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler"); - - D3D11_INPUT_ELEMENT_DESC quadLayout[] = - { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - - result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mPassThroughIL); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout"); - - result = device->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mPassThroughVS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader"); - - result = device->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mPassThroughPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader"); -} - -// parameters should be validated/clamped by caller -EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) -{ - if (!mSwapChain) - { - return EGL_SUCCESS; - } - - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - // Set vertices - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - return EGL_BAD_ACCESS; - } - - d3d11::PositionTexCoordVertex *vertices = static_cast(mappedResource.pData); - - // Create a quad in homogeneous coordinates - float x1 = (x / float(mWidth)) * 2.0f - 1.0f; - float y1 = (y / float(mHeight)) * 2.0f - 1.0f; - float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; - float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; - - float u1 = x / float(mWidth); - float v1 = y / float(mHeight); - float u2 = (x + width) / float(mWidth); - float v2 = (y + height) / float(mHeight); - - d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1); - d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); - d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); - d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); - - deviceContext->Unmap(mQuadVB, 0); - - static UINT stride = sizeof(d3d11::PositionTexCoordVertex); - static UINT startIdx = 0; - deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx); - - // Apply state - deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); - - static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; - deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); - - deviceContext->RSSetState(NULL); - - // Apply shaders - deviceContext->IASetInputLayout(mPassThroughIL); - deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - deviceContext->VSSetShader(mPassThroughVS, NULL, 0); - deviceContext->PSSetShader(mPassThroughPS, NULL, 0); - deviceContext->GSSetShader(NULL, NULL, 0); - - // Apply render targets - mRenderer->setOneTimeRenderTarget(mBackBufferRTView); - - // Set the viewport - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = mWidth; - viewport.Height = mHeight; - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - deviceContext->RSSetViewports(1, &viewport); - - // Apply textures - deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView); - deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); - - // Draw - deviceContext->Draw(4, 0); - result = mSwapChain->Present(mSwapInterval, 0); - - if (result == DXGI_ERROR_DEVICE_REMOVED) - { - HRESULT removedReason = device->GetDeviceRemovedReason(); - ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason); - return EGL_CONTEXT_LOST; - } - else if (result == DXGI_ERROR_DEVICE_RESET) - { - ERR("Present failed: the D3D11 device was reset from a bad command."); - return EGL_CONTEXT_LOST; - } - else if (FAILED(result)) - { - ERR("Present failed with error code 0x%08X", result); - } - - // Unbind - static ID3D11ShaderResourceView *const nullSRV = NULL; - deviceContext->PSSetShaderResources(0, 1, &nullSRV); - - mRenderer->unapplyRenderTargets(); - mRenderer->markAllStateDirty(); - - return EGL_SUCCESS; -} - -// Increments refcount on texture. -// caller must Release() the returned texture -ID3D11Texture2D *SwapChain11::getOffscreenTexture() -{ - if (mOffscreenTexture) - { - mOffscreenTexture->AddRef(); - } - - return mOffscreenTexture; -} - -// Increments refcount on view. -// caller must Release() the returned view -ID3D11RenderTargetView *SwapChain11::getRenderTarget() -{ - if (mOffscreenRTView) - { - mOffscreenRTView->AddRef(); - } - - return mOffscreenRTView; -} - -// Increments refcount on view. -// caller must Release() the returned view -ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource() -{ - if (mOffscreenSRView) - { - mOffscreenSRView->AddRef(); - } - - return mOffscreenSRView; -} - -// Increments refcount on view. -// caller must Release() the returned view -ID3D11DepthStencilView *SwapChain11::getDepthStencil() -{ - if (mDepthStencilDSView) - { - mDepthStencilDSView->AddRef(); - } - - return mDepthStencilDSView; -} - -ID3D11Texture2D *SwapChain11::getDepthStencilTexture() -{ - if (mDepthStencilTexture) - { - mDepthStencilTexture->AddRef(); - } - - return mDepthStencilTexture; -} - -SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain)); - return static_cast(swapChain); -} - -void SwapChain11::recreate() -{ - // possibly should use this method instead of reset -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h deleted file mode 100644 index 2a030c839d..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// SwapChain11.h: Defines a back-end specific class for the D3D11 swap chain. - -#ifndef LIBGLESV2_RENDERER_SWAPCHAIN11_H_ -#define LIBGLESV2_RENDERER_SWAPCHAIN11_H_ - -#include "common/angleutils.h" -#include "libGLESv2/renderer/SwapChain.h" - -namespace rx -{ -class Renderer11; - -class SwapChain11 : public SwapChain -{ - public: - SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat); - virtual ~SwapChain11(); - - EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); - virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); - virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); - virtual void recreate(); - - virtual ID3D11Texture2D *getOffscreenTexture(); - virtual ID3D11RenderTargetView *getRenderTarget(); - virtual ID3D11ShaderResourceView *getRenderTargetShaderResource(); - - virtual ID3D11Texture2D *getDepthStencilTexture(); - virtual ID3D11DepthStencilView *getDepthStencil(); - - EGLint getWidth() const { return mWidth; } - EGLint getHeight() const { return mHeight; } - - static SwapChain11 *makeSwapChain11(SwapChain *swapChain); - - private: - DISALLOW_COPY_AND_ASSIGN(SwapChain11); - - void release(); - void initPassThroughResources(); - void releaseOffscreenTexture(); - EGLint resetOffscreenTexture(int backbufferWidth, int backbufferHeight); - - Renderer11 *mRenderer; - EGLint mHeight; - EGLint mWidth; - bool mAppCreatedShareHandle; - unsigned int mSwapInterval; - bool mPassThroughResourcesInit; - - IDXGISwapChain *mSwapChain; - - ID3D11Texture2D *mBackBufferTexture; - ID3D11RenderTargetView *mBackBufferRTView; - - ID3D11Texture2D *mOffscreenTexture; - ID3D11RenderTargetView *mOffscreenRTView; - ID3D11ShaderResourceView *mOffscreenSRView; - - ID3D11Texture2D *mDepthStencilTexture; - ID3D11DepthStencilView *mDepthStencilDSView; - - ID3D11Buffer *mQuadVB; - ID3D11SamplerState *mPassThroughSampler; - ID3D11InputLayout *mPassThroughIL; - ID3D11VertexShader *mPassThroughVS; - ID3D11PixelShader *mPassThroughPS; -}; - -} -#endif // LIBGLESV2_RENDERER_SWAPCHAIN11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.cpp deleted file mode 100644 index f57a874688..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.cpp +++ /dev/null @@ -1,449 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain. - -#include "libGLESv2/renderer/SwapChain9.h" -#include "libGLESv2/renderer/renderer9_utils.h" -#include "libGLESv2/renderer/Renderer9.h" - -namespace rx -{ - -SwapChain9::SwapChain9(Renderer9 *renderer, HWND window, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat) - : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) -{ - mSwapChain = NULL; - mBackBuffer = NULL; - mDepthStencil = NULL; - mRenderTarget = NULL; - mOffscreenTexture = NULL; - mWidth = -1; - mHeight = -1; - mSwapInterval = -1; -} - -SwapChain9::~SwapChain9() -{ - release(); -} - -void SwapChain9::release() -{ - if (mSwapChain) - { - mSwapChain->Release(); - mSwapChain = NULL; - } - - if (mBackBuffer) - { - mBackBuffer->Release(); - mBackBuffer = NULL; - } - - if (mDepthStencil) - { - mDepthStencil->Release(); - mDepthStencil = NULL; - } - - if (mRenderTarget) - { - mRenderTarget->Release(); - mRenderTarget = NULL; - } - - if (mOffscreenTexture) - { - mOffscreenTexture->Release(); - mOffscreenTexture = NULL; - } - - if (mWindow) - mShareHandle = NULL; -} - -static DWORD convertInterval(EGLint interval) -{ - switch(interval) - { - case 0: return D3DPRESENT_INTERVAL_IMMEDIATE; - case 1: return D3DPRESENT_INTERVAL_ONE; - case 2: return D3DPRESENT_INTERVAL_TWO; - case 3: return D3DPRESENT_INTERVAL_THREE; - case 4: return D3DPRESENT_INTERVAL_FOUR; - default: UNREACHABLE(); - } - - return D3DPRESENT_INTERVAL_DEFAULT; -} - -EGLint SwapChain9::resize(int backbufferWidth, int backbufferHeight) -{ - // D3D9 does not support resizing swap chains without recreating them - return reset(backbufferWidth, backbufferHeight, mSwapInterval); -} - -EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) -{ - IDirect3DDevice9 *device = mRenderer->getDevice(); - - if (device == NULL) - { - return EGL_BAD_ACCESS; - } - - // Evict all non-render target textures to system memory and release all resources - // before reallocating them to free up as much video memory as possible. - device->EvictManagedResources(); - - HRESULT result; - - // Release specific resources to free up memory for the new render target, while the - // old render target still exists for the purpose of preserving its contents. - if (mSwapChain) - { - mSwapChain->Release(); - mSwapChain = NULL; - } - - if (mBackBuffer) - { - mBackBuffer->Release(); - mBackBuffer = NULL; - } - - if (mOffscreenTexture) - { - mOffscreenTexture->Release(); - mOffscreenTexture = NULL; - } - - if (mDepthStencil) - { - mDepthStencil->Release(); - mDepthStencil = NULL; - } - - HANDLE *pShareHandle = NULL; - if (!mWindow && mRenderer->getShareHandleSupport()) - { - pShareHandle = &mShareHandle; - } - - // CreateTexture will fail on zero dimensions, so just release old target - if (!backbufferWidth || !backbufferHeight) - { - if (mRenderTarget) - { - mRenderTarget->Release(); - mRenderTarget = NULL; - } - - mWidth = backbufferWidth; - mHeight = backbufferHeight; - - return EGL_SUCCESS; - } - - result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, - gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat), D3DPOOL_DEFAULT, - &mOffscreenTexture, pShareHandle); - if (FAILED(result)) - { - ERR("Could not create offscreen texture: %08lX", result); - release(); - - if (d3d9::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } - } - - IDirect3DSurface9 *oldRenderTarget = mRenderTarget; - - result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget); - ASSERT(SUCCEEDED(result)); - - if (oldRenderTarget) - { - RECT rect = - { - 0, 0, - mWidth, mHeight - }; - - if (rect.right > static_cast(backbufferWidth)) - { - rect.right = backbufferWidth; - } - - if (rect.bottom > static_cast(backbufferHeight)) - { - rect.bottom = backbufferHeight; - } - - mRenderer->endScene(); - - result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE); - ASSERT(SUCCEEDED(result)); - - oldRenderTarget->Release(); - } - - if (mWindow) - { - D3DPRESENT_PARAMETERS presentParameters = {0}; - presentParameters.AutoDepthStencilFormat = gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat); - presentParameters.BackBufferCount = 1; - presentParameters.BackBufferFormat = gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat); - presentParameters.EnableAutoDepthStencil = FALSE; - presentParameters.Flags = 0; - presentParameters.hDeviceWindow = mWindow; - presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented - presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented - presentParameters.PresentationInterval = convertInterval(swapInterval); - presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; - presentParameters.Windowed = TRUE; - presentParameters.BackBufferWidth = backbufferWidth; - presentParameters.BackBufferHeight = backbufferHeight; - - // http://crbug.com/140239 - // http://crbug.com/143434 - // - // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width - // when using the integrated Intel. This rounds the width up rather than down. - // - // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID - // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur. - if (mRenderer->getAdapterVendor() == VENDOR_ID_INTEL) - { - presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64; - } - - result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST); - - ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); - release(); - - if (d3d9::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } - } - - result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); - ASSERT(SUCCEEDED(result)); - InvalidateRect(mWindow, NULL, FALSE); - } - - if (mDepthBufferFormat != GL_NONE) - { - result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, - gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat), - D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL); - - ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); - release(); - - if (d3d9::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } - } - } - - mWidth = backbufferWidth; - mHeight = backbufferHeight; - mSwapInterval = swapInterval; - - return EGL_SUCCESS; -} - -// parameters should be validated/clamped by caller -EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) -{ - if (!mSwapChain) - { - return EGL_SUCCESS; - } - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - // Disable all pipeline operations - device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); - device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - device->SetRenderState(D3DRS_STENCILENABLE, FALSE); - device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); - device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); - device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); - device->SetPixelShader(NULL); - device->SetVertexShader(NULL); - - device->SetRenderTarget(0, mBackBuffer); - device->SetDepthStencilSurface(NULL); - - device->SetTexture(0, mOffscreenTexture); - device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); - - D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f}; - device->SetViewport(&viewport); - - float x1 = x - 0.5f; - float y1 = (mHeight - y - height) - 0.5f; - float x2 = (x + width) - 0.5f; - float y2 = (mHeight - y) - 0.5f; - - float u1 = x / float(mWidth); - float v1 = y / float(mHeight); - float u2 = (x + width) / float(mWidth); - float v2 = (y + height) / float(mHeight); - - float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2}, - {x2, y1, 0.0f, 1.0f, u2, v2}, - {x2, y2, 0.0f, 1.0f, u2, v1}, - {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v - - mRenderer->startScene(); - device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); - mRenderer->endScene(); - - device->SetTexture(0, NULL); - - RECT rect = - { - x, mHeight - y - height, - x + width, mHeight - y - }; - - HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0); - - mRenderer->markAllStateDirty(); - - if (d3d9::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) - { - return EGL_BAD_ALLOC; - } - - ASSERT(SUCCEEDED(result)); - - return EGL_SUCCESS; -} - -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *SwapChain9::getRenderTarget() -{ - if (mRenderTarget) - { - mRenderTarget->AddRef(); - } - - return mRenderTarget; -} - -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *SwapChain9::getDepthStencil() -{ - if (mDepthStencil) - { - mDepthStencil->AddRef(); - } - - return mDepthStencil; -} - -// Increments refcount on texture. -// caller must Release() the returned texture -IDirect3DTexture9 *SwapChain9::getOffscreenTexture() -{ - if (mOffscreenTexture) - { - mOffscreenTexture->AddRef(); - } - - return mOffscreenTexture; -} - -SwapChain9 *SwapChain9::makeSwapChain9(SwapChain *swapChain) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain9*, swapChain)); - return static_cast(swapChain); -} - -void SwapChain9::recreate() -{ - if (!mSwapChain) - { - return; - } - - IDirect3DDevice9 *device = mRenderer->getDevice(); - if (device == NULL) - { - return; - } - - D3DPRESENT_PARAMETERS presentParameters; - HRESULT result = mSwapChain->GetPresentParameters(&presentParameters); - ASSERT(SUCCEEDED(result)); - - IDirect3DSwapChain9* newSwapChain = NULL; - result = device->CreateAdditionalSwapChain(&presentParameters, &newSwapChain); - if (FAILED(result)) - { - return; - } - - mSwapChain->Release(); - mSwapChain = newSwapChain; - - mBackBuffer->Release(); - result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); - ASSERT(SUCCEEDED(result)); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.h deleted file mode 100644 index 16a62bd86f..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// SwapChain9.h: Defines a back-end specific class for the D3D9 swap chain. - -#ifndef LIBGLESV2_RENDERER_SWAPCHAIN9_H_ -#define LIBGLESV2_RENDERER_SWAPCHAIN9_H_ - -#include "common/angleutils.h" -#include "libGLESv2/renderer/SwapChain.h" - -namespace rx -{ -class Renderer9; - -class SwapChain9 : public SwapChain -{ - public: - SwapChain9(Renderer9 *renderer, HWND window, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat); - virtual ~SwapChain9(); - - EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); - virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); - virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); - virtual void recreate(); - - virtual IDirect3DSurface9 *getRenderTarget(); - virtual IDirect3DSurface9 *getDepthStencil(); - virtual IDirect3DTexture9 *getOffscreenTexture(); - - static SwapChain9 *makeSwapChain9(SwapChain *swapChain); - - private: - DISALLOW_COPY_AND_ASSIGN(SwapChain9); - - void release(); - - Renderer9 *mRenderer; - EGLint mHeight; - EGLint mWidth; - EGLint mSwapInterval; - - IDirect3DSwapChain9 *mSwapChain; - IDirect3DSurface9 *mBackBuffer; - IDirect3DSurface9 *mRenderTarget; - IDirect3DSurface9 *mDepthStencil; - IDirect3DTexture9* mOffscreenTexture; -}; - -} -#endif // LIBGLESV2_RENDERER_SWAPCHAIN9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp deleted file mode 100644 index 32a407a988..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp +++ /dev/null @@ -1,667 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived -// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. - -#include "libGLESv2/renderer/TextureStorage11.h" - -#include "libGLESv2/renderer/Renderer11.h" -#include "libGLESv2/renderer/RenderTarget11.h" -#include "libGLESv2/renderer/SwapChain11.h" -#include "libGLESv2/renderer/renderer11_utils.h" - -#include "libGLESv2/utilities.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags) - : mBindFlags(bindFlags), - mLodOffset(0), - mMipLevels(0), - mTexture(NULL), - mTextureFormat(DXGI_FORMAT_UNKNOWN), - mShaderResourceFormat(DXGI_FORMAT_UNKNOWN), - mRenderTargetFormat(DXGI_FORMAT_UNKNOWN), - mDepthStencilFormat(DXGI_FORMAT_UNKNOWN), - mSRV(NULL), - mTextureWidth(0), - mTextureHeight(0) -{ - mRenderer = Renderer11::makeRenderer11(renderer); -} - -TextureStorage11::~TextureStorage11() -{ -} - -TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage)); - return static_cast(storage); -} - -DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable) -{ - UINT bindFlags = D3D11_BIND_SHADER_RESOURCE; - - if (d3d11::IsDepthStencilFormat(format)) - { - bindFlags |= D3D11_BIND_DEPTH_STENCIL; - } - else if(forceRenderable || (TextureStorage11::IsTextureFormatRenderable(format) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE))) - { - bindFlags |= D3D11_BIND_RENDER_TARGET; - } - return bindFlags; -} - -bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format) -{ - switch(format) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - case DXGI_FORMAT_A8_UNORM: - case DXGI_FORMAT_R32G32B32A32_FLOAT: - case DXGI_FORMAT_R16G16B16A16_FLOAT: - case DXGI_FORMAT_B8G8R8A8_UNORM: - case DXGI_FORMAT_R8_UNORM: - case DXGI_FORMAT_R8G8_UNORM: - case DXGI_FORMAT_R16_FLOAT: - case DXGI_FORMAT_R16G16_FLOAT: - return true; - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_R32G32B32_FLOAT: // not renderable on all devices - return false; - default: - UNREACHABLE(); - return false; - } -} - -UINT TextureStorage11::getBindFlags() const -{ - return mBindFlags; -} - -ID3D11Texture2D *TextureStorage11::getBaseTexture() const -{ - return mTexture; -} - -int TextureStorage11::getLodOffset() const -{ - return mLodOffset; -} - -bool TextureStorage11::isRenderTarget() const -{ - return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0; -} - -bool TextureStorage11::isManaged() const -{ - return false; -} - -int TextureStorage11::levelCount() -{ - int levels = 0; - if (getBaseTexture()) - { - levels = mMipLevels - getLodOffset(); - } - return levels; -} - -UINT TextureStorage11::getSubresourceIndex(int level, int faceIndex) -{ - UINT index = 0; - if (getBaseTexture()) - { - index = D3D11CalcSubresource(level, faceIndex, mMipLevels); - } - return index; -} - -bool TextureStorage11::updateSubresourceLevel(ID3D11Texture2D *srcTexture, unsigned int sourceSubresource, - int level, int face, GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height) -{ - if (srcTexture) - { - // Round up the width and height to the nearest multiple of dimension alignment - unsigned int dimensionAlignment = d3d11::GetTextureFormatDimensionAlignment(mTextureFormat); - width = width + dimensionAlignment - 1 - (width - 1) % dimensionAlignment; - height = height + dimensionAlignment - 1 - (height - 1) % dimensionAlignment; - - D3D11_BOX srcBox; - srcBox.left = xoffset; - srcBox.top = yoffset; - srcBox.right = xoffset + width; - srcBox.bottom = yoffset + height; - srcBox.front = 0; - srcBox.back = 1; - - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - ASSERT(getBaseTexture()); - context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level + mLodOffset, face), - xoffset, yoffset, 0, srcTexture, sourceSubresource, &srcBox); - return true; - } - - return false; -} - -void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest) -{ - if (source && dest) - { - ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView(); - ID3D11RenderTargetView *destRTV = dest->getRenderTargetView(); - - if (sourceSRV && destRTV) - { - gl::Rectangle sourceArea; - sourceArea.x = 0; - sourceArea.y = 0; - sourceArea.width = source->getWidth(); - sourceArea.height = source->getHeight(); - - gl::Rectangle destArea; - destArea.x = 0; - destArea.y = 0; - destArea.width = dest->getWidth(); - destArea.height = dest->getHeight(); - - mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(), - destRTV, destArea, dest->getWidth(), dest->getHeight(), - GL_RGBA); - } - } -} - -TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain) - : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE) -{ - mTexture = swapchain->getOffscreenTexture(); - mSRV = swapchain->getRenderTargetShaderResource(); - - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mRenderTarget[i] = NULL; - } - - D3D11_TEXTURE2D_DESC texDesc; - mTexture->GetDesc(&texDesc); - mMipLevels = texDesc.MipLevels; - mTextureFormat = texDesc.Format; - mTextureWidth = texDesc.Width; - mTextureHeight = texDesc.Height; - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - mSRV->GetDesc(&srvDesc); - mShaderResourceFormat = srvDesc.Format; - - ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget(); - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - offscreenRTV->GetDesc(&rtvDesc); - mRenderTargetFormat = rtvDesc.Format; - offscreenRTV->Release(); - - mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; -} - -TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) - : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()), usage, forceRenderable)) -{ - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mRenderTarget[i] = NULL; - } - - DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()); - if (d3d11::IsDepthStencilFormat(convertedFormat)) - { - mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); - mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat); - mDepthStencilFormat = convertedFormat; - mRenderTargetFormat = DXGI_FORMAT_UNKNOWN; - } - else - { - mTextureFormat = convertedFormat; - mShaderResourceFormat = convertedFormat; - mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; - mRenderTargetFormat = convertedFormat; - } - - // if the width or height is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (width > 0 && height > 0) - { - // adjust size if needed for compressed textures - gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset); - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE2D_DESC desc; - desc.Width = width; // Compressed texture size constraints? - desc.Height = height; - desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0; - desc.ArraySize = 1; - desc.Format = mTextureFormat; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = getBindFlags(); - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); - - // this can happen from windows TDR - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - gl::error(GL_OUT_OF_MEMORY); - } - else if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - ERR("Creating image failed."); - gl::error(GL_OUT_OF_MEMORY); - } - else - { - mTexture->GetDesc(&desc); - mMipLevels = desc.MipLevels; - mTextureWidth = desc.Width; - mTextureHeight = desc.Height; - } - } -} - -TextureStorage11_2D::~TextureStorage11_2D() -{ - if (mTexture) - { - mTexture->Release(); - mTexture = NULL; - } - - if (mSRV) - { - mSRV->Release(); - mSRV = NULL; - } - - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - delete mRenderTarget[i]; - mRenderTarget[i] = NULL; - } -} - -TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage)); - return static_cast(storage); -} - -RenderTarget *TextureStorage11_2D::getRenderTarget(int level) -{ - if (level >= 0 && level < static_cast(mMipLevels)) - { - if (!mRenderTarget[level]) - { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MostDetailedMip = level; - srvDesc.Texture2D.MipLevels = 1; - - ID3D11ShaderResourceView *srv; - result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); - - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtvDesc.Texture2D.MipSlice = level; - - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); - - if (result == E_OUTOFMEMORY) - { - srv->Release(); - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 - // also needs to keep a reference to the texture. - mTexture->AddRef(); - - mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, - std::max(mTextureWidth >> level, 1U), - std::max(mTextureHeight >> level, 1U)); - } - else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = mDepthStencilFormat; - dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; - dsvDesc.Texture2D.MipSlice = level; - dsvDesc.Flags = 0; - - ID3D11DepthStencilView *dsv; - result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); - - if (result == E_OUTOFMEMORY) - { - srv->Release(); - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 - // also needs to keep a reference to the texture. - mTexture->AddRef(); - - mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, - std::max(mTextureWidth >> level, 1U), - std::max(mTextureHeight >> level, 1U)); - } - else - { - UNREACHABLE(); - } - } - - return mRenderTarget[level]; - } - else - { - return NULL; - } -} - -ID3D11ShaderResourceView *TextureStorage11_2D::getSRV() -{ - if (!mSRV) - { - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels); - srvDesc.Texture2D.MostDetailedMip = 0; - - HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV); - - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - } - - return mSRV; -} - -void TextureStorage11_2D::generateMipmap(int level) -{ - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level)); - - generateMipmapLayer(source, dest); -} - -TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) - : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()), usage, forceRenderable)) -{ - for (unsigned int i = 0; i < 6; i++) - { - for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++) - { - mRenderTarget[i][j] = NULL; - } - } - - DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()); - if (d3d11::IsDepthStencilFormat(convertedFormat)) - { - mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); - mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat); - mDepthStencilFormat = convertedFormat; - mRenderTargetFormat = DXGI_FORMAT_UNKNOWN; - } - else - { - mTextureFormat = convertedFormat; - mShaderResourceFormat = convertedFormat; - mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; - mRenderTargetFormat = convertedFormat; - } - - // if the size is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (size > 0) - { - // adjust size if needed for compressed textures - int height = size; - gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset); - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE2D_DESC desc; - desc.Width = size; - desc.Height = size; - desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0; - desc.ArraySize = 6; - desc.Format = mTextureFormat; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = getBindFlags(); - desc.CPUAccessFlags = 0; - desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; - - HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); - - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - ERR("Creating image failed."); - gl::error(GL_OUT_OF_MEMORY); - } - else - { - mTexture->GetDesc(&desc); - mMipLevels = desc.MipLevels; - mTextureWidth = desc.Width; - mTextureHeight = desc.Height; - } - } -} - -TextureStorage11_Cube::~TextureStorage11_Cube() -{ - if (mTexture) - { - mTexture->Release(); - mTexture = NULL; - } - - if (mSRV) - { - mSRV->Release(); - mSRV = NULL; - } - - for (unsigned int i = 0; i < 6; i++) - { - for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++) - { - delete mRenderTarget[i][j]; - mRenderTarget[i][j] = NULL; - } - } -} - -TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage)); - return static_cast(storage); -} - -RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level) -{ - unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget); - if (level >= 0 && level < static_cast(mMipLevels)) - { - if (!mRenderTarget[faceIdx][level]) - { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; - srvDesc.Texture2DArray.MostDetailedMip = level; - srvDesc.Texture2DArray.MipLevels = 1; - srvDesc.Texture2DArray.FirstArraySlice = faceIdx; - srvDesc.Texture2DArray.ArraySize = 1; - - ID3D11ShaderResourceView *srv; - result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); - - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = level; - rtvDesc.Texture2DArray.FirstArraySlice = faceIdx; - rtvDesc.Texture2DArray.ArraySize = 1; - - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); - - if (result == E_OUTOFMEMORY) - { - srv->Release(); - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 - // also needs to keep a reference to the texture. - mTexture->AddRef(); - - mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, - std::max(mTextureWidth >> level, 1U), - std::max(mTextureHeight >> level, 1U)); - } - else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = mRenderTargetFormat; - dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; - dsvDesc.Texture2DArray.MipSlice = level; - dsvDesc.Texture2DArray.FirstArraySlice = faceIdx; - dsvDesc.Texture2DArray.ArraySize = 1; - - ID3D11DepthStencilView *dsv; - result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); - - if (result == E_OUTOFMEMORY) - { - srv->Release(); - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 - // also needs to keep a reference to the texture. - mTexture->AddRef(); - - mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, - std::max(mTextureWidth >> level, 1U), - std::max(mTextureHeight >> level, 1U)); - } - else - { - UNREACHABLE(); - } - } - - return mRenderTarget[faceIdx][level]; - } - else - { - return NULL; - } -} - -ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV() -{ - if (!mSRV) - { - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; - srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels); - srvDesc.TextureCube.MostDetailedMip = 0; - - HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV); - - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - } - - return mSRV; -} - -void TextureStorage11_Cube::generateMipmap(int face, int level) -{ - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level)); - - generateMipmapLayer(source, dest); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.h deleted file mode 100644 index 3c5ded05b8..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.h +++ /dev/null @@ -1,120 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TextureStorage11.h: Defines the abstract rx::TextureStorage11 class and its concrete derived -// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. - -#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ -#define LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ - -#include "libGLESv2/Texture.h" -#include "libGLESv2/renderer/TextureStorage.h" - -namespace rx -{ -class RenderTarget; -class RenderTarget11; -class Renderer; -class Renderer11; -class SwapChain11; - -class TextureStorage11 : public TextureStorage -{ - public: - TextureStorage11(Renderer *renderer, UINT bindFlags); - virtual ~TextureStorage11(); - - static TextureStorage11 *makeTextureStorage11(TextureStorage *storage); - - static DWORD GetTextureBindFlags(DXGI_FORMAT d3dfmt, GLenum glusage, bool forceRenderable); - static bool IsTextureFormatRenderable(DXGI_FORMAT format); - - UINT getBindFlags() const; - - virtual ID3D11Texture2D *getBaseTexture() const; - virtual ID3D11ShaderResourceView *getSRV() = 0; - virtual RenderTarget *getRenderTarget() { return getRenderTarget(0); } - virtual RenderTarget *getRenderTarget(int level) { return NULL; } - virtual RenderTarget *getRenderTarget(GLenum faceTarget) { return getRenderTarget(faceTarget, 0); } - virtual RenderTarget *getRenderTarget(GLenum faceTarget, int level) { return NULL; } - - virtual void generateMipmap(int level) {}; - virtual void generateMipmap(int face, int level) {}; - - virtual int getLodOffset() const; - virtual bool isRenderTarget() const; - virtual bool isManaged() const; - virtual int levelCount(); - UINT getSubresourceIndex(int level, int faceTarget); - - bool updateSubresourceLevel(ID3D11Texture2D *texture, unsigned int sourceSubresource, int level, - int faceTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - - protected: - void generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest); - - Renderer11 *mRenderer; - int mLodOffset; - unsigned int mMipLevels; - - ID3D11Texture2D *mTexture; - DXGI_FORMAT mTextureFormat; - DXGI_FORMAT mShaderResourceFormat; - DXGI_FORMAT mRenderTargetFormat; - DXGI_FORMAT mDepthStencilFormat; - unsigned int mTextureWidth; - unsigned int mTextureHeight; - - ID3D11ShaderResourceView *mSRV; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11); - - const UINT mBindFlags; -}; - -class TextureStorage11_2D : public TextureStorage11 -{ - public: - TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain); - TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); - virtual ~TextureStorage11_2D(); - - static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage); - - virtual ID3D11ShaderResourceView *getSRV(); - virtual RenderTarget *getRenderTarget(int level); - - virtual void generateMipmap(int level); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D); - - RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; -}; - -class TextureStorage11_Cube : public TextureStorage11 -{ - public: - TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); - virtual ~TextureStorage11_Cube(); - - static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage); - - virtual ID3D11ShaderResourceView *getSRV(); - virtual RenderTarget *getRenderTarget(GLenum faceTarget, int level); - - virtual void generateMipmap(int face, int level); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube); - - RenderTarget11 *mRenderTarget[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; -}; - -} - -#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage9.cpp deleted file mode 100644 index 8aa74a7cba..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage9.cpp +++ /dev/null @@ -1,328 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TextureStorage9.cpp: Implements the abstract rx::TextureStorage9 class and its concrete derived -// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the -// D3D9 texture. - -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/Renderer9.h" -#include "libGLESv2/renderer/TextureStorage9.h" -#include "libGLESv2/renderer/SwapChain9.h" -#include "libGLESv2/renderer/RenderTarget9.h" -#include "libGLESv2/renderer/renderer9_utils.h" -#include "libGLESv2/Texture.h" - -namespace rx -{ -TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage) - : mLodOffset(0), - mRenderer(Renderer9::makeRenderer9(renderer)), - mD3DUsage(usage), - mD3DPool(mRenderer->getTexturePool(usage)) -{ -} - -TextureStorage9::~TextureStorage9() -{ -} - -TextureStorage9 *TextureStorage9::makeTextureStorage9(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9*, storage)); - return static_cast(storage); -} - -DWORD TextureStorage9::GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable) -{ - DWORD d3dusage = 0; - - if (d3dfmt == D3DFMT_INTZ) - { - d3dusage |= D3DUSAGE_DEPTHSTENCIL; - } - else if(forceRenderable || (TextureStorage9::IsTextureFormatRenderable(d3dfmt) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE))) - { - d3dusage |= D3DUSAGE_RENDERTARGET; - } - return d3dusage; -} - -bool TextureStorage9::IsTextureFormatRenderable(D3DFORMAT format) -{ - if (format == D3DFMT_INTZ) - { - return true; - } - switch(format) - { - case D3DFMT_L8: - case D3DFMT_A8L8: - case D3DFMT_DXT1: - case D3DFMT_DXT3: - case D3DFMT_DXT5: - return false; - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: - case D3DFMT_A16B16G16R16F: - case D3DFMT_A32B32G32R32F: - return true; - default: - UNREACHABLE(); - } - - return false; -} - -bool TextureStorage9::isRenderTarget() const -{ - return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0; -} - -bool TextureStorage9::isManaged() const -{ - return (mD3DPool == D3DPOOL_MANAGED); -} - -D3DPOOL TextureStorage9::getPool() const -{ - return mD3DPool; -} - -DWORD TextureStorage9::getUsage() const -{ - return mD3DUsage; -} - -int TextureStorage9::getLodOffset() const -{ - return mLodOffset; -} - -int TextureStorage9::levelCount() -{ - return getBaseTexture() ? getBaseTexture()->GetLevelCount() - getLodOffset() : 0; -} - -TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain) : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET) -{ - IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture(); - mTexture = surfaceTexture; - mRenderTarget = NULL; - - initializeRenderTarget(); -} - -TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) - : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable)) -{ - mTexture = NULL; - mRenderTarget = NULL; - // if the width or height is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (width > 0 && height > 0) - { - IDirect3DDevice9 *device = mRenderer->getDevice(); - gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset); - HRESULT result = device->CreateTexture(width, height, levels ? levels + mLodOffset : 0, getUsage(), - mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - gl::error(GL_OUT_OF_MEMORY); - } - } - - initializeRenderTarget(); -} - -TextureStorage9_2D::~TextureStorage9_2D() -{ - if (mTexture) - { - mTexture->Release(); - } - - delete mRenderTarget; -} - -TextureStorage9_2D *TextureStorage9_2D::makeTextureStorage9_2D(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_2D*, storage)); - return static_cast(storage); -} - -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty) -{ - IDirect3DSurface9 *surface = NULL; - - if (mTexture) - { - HRESULT result = mTexture->GetSurfaceLevel(level + mLodOffset, &surface); - ASSERT(SUCCEEDED(result)); - - // With managed textures the driver needs to be informed of updates to the lower mipmap levels - if (level + mLodOffset != 0 && isManaged() && dirty) - { - mTexture->AddDirtyRect(NULL); - } - } - - return surface; -} - -RenderTarget *TextureStorage9_2D::getRenderTarget() -{ - return mRenderTarget; -} - -void TextureStorage9_2D::generateMipmap(int level) -{ - IDirect3DSurface9 *upper = getSurfaceLevel(level - 1, false); - IDirect3DSurface9 *lower = getSurfaceLevel(level, true); - - if (upper != NULL && lower != NULL) - { - mRenderer->boxFilter(upper, lower); - } - - if (upper != NULL) upper->Release(); - if (lower != NULL) lower->Release(); -} - -IDirect3DBaseTexture9 *TextureStorage9_2D::getBaseTexture() const -{ - return mTexture; -} - -void TextureStorage9_2D::initializeRenderTarget() -{ - ASSERT(mRenderTarget == NULL); - - if (mTexture != NULL && isRenderTarget()) - { - IDirect3DSurface9 *surface = getSurfaceLevel(0, false); - - mRenderTarget = new RenderTarget9(mRenderer, surface); - } -} - -TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) - : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable)) -{ - mTexture = NULL; - for (int i = 0; i < 6; ++i) - { - mRenderTarget[i] = NULL; - } - - // if the size is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (size > 0) - { - IDirect3DDevice9 *device = mRenderer->getDevice(); - int height = size; - gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset); - HRESULT result = device->CreateCubeTexture(size, levels ? levels + mLodOffset : 0, getUsage(), - mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - gl::error(GL_OUT_OF_MEMORY); - } - } - - initializeRenderTarget(); -} - -TextureStorage9_Cube::~TextureStorage9_Cube() -{ - if (mTexture) - { - mTexture->Release(); - } - - for (int i = 0; i < 6; ++i) - { - delete mRenderTarget[i]; - } -} - -TextureStorage9_Cube *TextureStorage9_Cube::makeTextureStorage9_Cube(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_Cube*, storage)); - return static_cast(storage); -} - -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty) -{ - IDirect3DSurface9 *surface = NULL; - - if (mTexture) - { - D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget); - HRESULT result = mTexture->GetCubeMapSurface(face, level + mLodOffset, &surface); - ASSERT(SUCCEEDED(result)); - - // With managed textures the driver needs to be informed of updates to the lower mipmap levels - if (level != 0 && isManaged() && dirty) - { - mTexture->AddDirtyRect(face, NULL); - } - } - - return surface; -} - -RenderTarget *TextureStorage9_Cube::getRenderTarget(GLenum faceTarget) -{ - return mRenderTarget[gl::TextureCubeMap::faceIndex(faceTarget)]; -} - -void TextureStorage9_Cube::generateMipmap(int face, int level) -{ - IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1, false); - IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true); - - if (upper != NULL && lower != NULL) - { - mRenderer->boxFilter(upper, lower); - } - - if (upper != NULL) upper->Release(); - if (lower != NULL) lower->Release(); -} - -IDirect3DBaseTexture9 *TextureStorage9_Cube::getBaseTexture() const -{ - return mTexture; -} - -void TextureStorage9_Cube::initializeRenderTarget() -{ - if (mTexture != NULL && isRenderTarget()) - { - IDirect3DSurface9 *surface = NULL; - - for (int i = 0; i < 6; ++i) - { - ASSERT(mRenderTarget[i] == NULL); - - surface = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, false); - - mRenderTarget[i] = new RenderTarget9(mRenderer, surface); - } - } -} - -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage9.h deleted file mode 100644 index 86f551a131..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage9.h +++ /dev/null @@ -1,109 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TextureStorage9.h: Defines the abstract rx::TextureStorage9 class and its concrete derived -// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the -// D3D9 texture. - -#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ -#define LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ - -#include "libGLESv2/renderer/TextureStorage.h" -#include "common/debug.h" - -namespace rx -{ -class Renderer9; -class SwapChain9; -class RenderTarget; -class RenderTarget9; -class Blit; - -class TextureStorage9 : public TextureStorage -{ - public: - TextureStorage9(Renderer *renderer, DWORD usage); - virtual ~TextureStorage9(); - - static TextureStorage9 *makeTextureStorage9(TextureStorage *storage); - - static DWORD GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable); - static bool IsTextureFormatRenderable(D3DFORMAT format); - - D3DPOOL getPool() const; - DWORD getUsage() const; - - virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0; - virtual RenderTarget *getRenderTarget() { return NULL; } - virtual RenderTarget *getRenderTarget(GLenum faceTarget) { return NULL; } - virtual void generateMipmap(int level) {}; - virtual void generateMipmap(int face, int level) {}; - - virtual int getLodOffset() const; - virtual bool isRenderTarget() const; - virtual bool isManaged() const; - virtual int levelCount(); - - protected: - int mLodOffset; - Renderer9 *mRenderer; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage9); - - const DWORD mD3DUsage; - const D3DPOOL mD3DPool; -}; - -class TextureStorage9_2D : public TextureStorage9 -{ - public: - TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain); - TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); - virtual ~TextureStorage9_2D(); - - static TextureStorage9_2D *makeTextureStorage9_2D(TextureStorage *storage); - - IDirect3DSurface9 *getSurfaceLevel(int level, bool dirty); - virtual RenderTarget *getRenderTarget(); - virtual IDirect3DBaseTexture9 *getBaseTexture() const; - virtual void generateMipmap(int level); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage9_2D); - - void initializeRenderTarget(); - - IDirect3DTexture9 *mTexture; - RenderTarget9 *mRenderTarget; -}; - -class TextureStorage9_Cube : public TextureStorage9 -{ - public: - TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); - virtual ~TextureStorage9_Cube(); - - static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage); - - IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level, bool dirty); - virtual RenderTarget *getRenderTarget(GLenum faceTarget); - virtual IDirect3DBaseTexture9 *getBaseTexture() const; - virtual void generateMipmap(int face, int level); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage9_Cube); - - void initializeRenderTarget(); - - IDirect3DCubeTexture9 *mTexture; - RenderTarget9 *mRenderTarget[6]; -}; - -} - -#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ - diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp deleted file mode 100644 index 521da80c3d..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp +++ /dev/null @@ -1,440 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation. - -#include "libGLESv2/renderer/VertexBuffer11.h" -#include "libGLESv2/renderer/BufferStorage.h" - -#include "libGLESv2/Buffer.h" -#include "libGLESv2/renderer/Renderer11.h" -#include "libGLESv2/Context.h" - -namespace rx -{ - -VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer) -{ - mBuffer = NULL; - mBufferSize = 0; - mDynamicUsage = false; -} - -VertexBuffer11::~VertexBuffer11() -{ - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - } -} - -bool VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) -{ - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - } - - updateSerial(); - - if (size > 0) - { - ID3D11Device* dxDevice = mRenderer->getDevice(); - - D3D11_BUFFER_DESC bufferDesc; - bufferDesc.ByteWidth = size; - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - bufferDesc.MiscFlags = 0; - bufferDesc.StructureByteStride = 0; - - HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); - if (FAILED(result)) - { - return false; - } - } - - mBufferSize = size; - mDynamicUsage = dynamicUsage; - return true; -} - -VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer)); - return static_cast(vetexBuffer); -} - -bool VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, - GLsizei instances, unsigned int offset) -{ - if (mBuffer) - { - gl::Buffer *buffer = attrib.mBoundBuffer.get(); - - int inputStride = attrib.stride(); - const VertexConverter &converter = getVertexConversion(attrib); - - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Vertex buffer map failed with error 0x%08x", result); - return false; - } - - char* output = reinterpret_cast(mappedResource.pData) + offset; - - const char *input = NULL; - if (buffer) - { - BufferStorage *storage = buffer->getStorage(); - input = static_cast(storage->getData()) + static_cast(attrib.mOffset); - } - else - { - input = static_cast(attrib.mPointer); - } - - if (instances == 0 || attrib.mDivisor == 0) - { - input += inputStride * start; - } - - converter.conversionFunc(input, inputStride, count, output); - - dxContext->Unmap(mBuffer, 0); - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -bool VertexBuffer11::storeRawData(const void* data, unsigned int size, unsigned int offset) -{ - if (mBuffer) - { - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Vertex buffer map failed with error 0x%08x", result); - return false; - } - - char* bufferData = static_cast(mappedResource.pData); - memcpy(bufferData + offset, data, size); - - dxContext->Unmap(mBuffer, 0); - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -bool VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, - GLsizei instances, unsigned int *outSpaceRequired) const -{ - unsigned int elementSize = getVertexConversion(attrib).outputElementSize; - - unsigned int elementCount = 0; - if (instances == 0 || attrib.mDivisor == 0) - { - elementCount = count; - } - else - { - if (static_cast(instances) < std::numeric_limits::max() - (attrib.mDivisor - 1)) - { - // Round up - elementCount = (static_cast(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor; - } - else - { - elementCount = instances / attrib.mDivisor; - } - } - - if (elementSize <= std::numeric_limits::max() / elementCount) - { - if (outSpaceRequired) - { - *outSpaceRequired = elementSize * elementCount; - } - return true; - } - else - { - return false; - } -} - -bool VertexBuffer11::requiresConversion(const gl::VertexAttribute &attrib) const -{ - return !getVertexConversion(attrib).identity; -} - -unsigned int VertexBuffer11::getBufferSize() const -{ - return mBufferSize; -} - -bool VertexBuffer11::setBufferSize(unsigned int size) -{ - if (size > mBufferSize) - { - return initialize(size, mDynamicUsage); - } - else - { - return true; - } -} - -bool VertexBuffer11::discard() -{ - if (mBuffer) - { - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Vertex buffer map failed with error 0x%08x", result); - return false; - } - - dxContext->Unmap(mBuffer, 0); - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -unsigned int VertexBuffer11::getVertexSize(const gl::VertexAttribute &attrib) const -{ - return getVertexConversion(attrib).outputElementSize; -} - -DXGI_FORMAT VertexBuffer11::getDXGIFormat(const gl::VertexAttribute &attrib) const -{ - return getVertexConversion(attrib).dxgiFormat; -} - -ID3D11Buffer *VertexBuffer11::getBuffer() const -{ - return mBuffer; -} - -template -static void copyVertexData(const void *input, unsigned int stride, unsigned int count, void *output) -{ - unsigned int attribSize = sizeof(T) * componentCount; - - if (attribSize == stride && !widen) - { - memcpy(output, input, count * attribSize); - } - else - { - unsigned int outputStride = widen ? 4 : componentCount; - T defaultVal = normalized ? std::numeric_limits::max() : T(1); - - for (unsigned int i = 0; i < count; i++) - { - const T *offsetInput = reinterpret_cast(reinterpret_cast(input) + i * stride); - T *offsetOutput = reinterpret_cast(output) + i * outputStride; - - for (unsigned int j = 0; j < componentCount; j++) - { - offsetOutput[j] = offsetInput[j]; - } - - if (widen) - { - offsetOutput[3] = defaultVal; - } - } - } -} - -template -static void copyFixedVertexData(const void* input, unsigned int stride, unsigned int count, void* output) -{ - static const float divisor = 1.0f / (1 << 16); - - for (unsigned int i = 0; i < count; i++) - { - const GLfixed* offsetInput = reinterpret_cast(reinterpret_cast(input) + stride * i); - float* offsetOutput = reinterpret_cast(output) + i * componentCount; - - for (unsigned int j = 0; j < componentCount; j++) - { - offsetOutput[j] = static_cast(offsetInput[j]) * divisor; - } - } -} - -template -static void copyToFloatVertexData(const void* input, unsigned int stride, unsigned int count, void* output) -{ - typedef std::numeric_limits NL; - - for (unsigned int i = 0; i < count; i++) - { - const T *offsetInput = reinterpret_cast(reinterpret_cast(input) + stride * i); - float *offsetOutput = reinterpret_cast(output) + i * componentCount; - - for (unsigned int j = 0; j < componentCount; j++) - { - if (normalized) - { - if (NL::is_signed) - { - const float divisor = 1.0f / (2 * static_cast(NL::max()) + 1); - offsetOutput[j] = (2 * static_cast(offsetInput[j]) + 1) * divisor; - } - else - { - offsetOutput[j] = static_cast(offsetInput[j]) / NL::max(); - } - } - else - { - offsetOutput[j] = static_cast(offsetInput[j]); - } - } - } -} - -const VertexBuffer11::VertexConverter VertexBuffer11::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = -{ - { // GL_BYTE - { // unnormalized - { ©ToFloatVertexData, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©VertexData, true, DXGI_FORMAT_R8_SNORM, 1 }, - { ©VertexData, true, DXGI_FORMAT_R8G8_SNORM, 2 }, - { ©VertexData, false, DXGI_FORMAT_R8G8B8A8_SNORM, 4 }, - { ©VertexData, true, DXGI_FORMAT_R8G8B8A8_SNORM, 4 }, - }, - }, - { // GL_UNSIGNED_BYTE - { // unnormalized - { ©ToFloatVertexData, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©VertexData, true, DXGI_FORMAT_R8_UNORM, 1 }, - { ©VertexData, true, DXGI_FORMAT_R8G8_UNORM, 2 }, - { ©VertexData, false, DXGI_FORMAT_R8G8B8A8_UNORM, 4 }, - { ©VertexData, true, DXGI_FORMAT_R8G8B8A8_UNORM, 4 }, - }, - }, - { // GL_SHORT - { // unnormalized - { ©ToFloatVertexData, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©VertexData, true, DXGI_FORMAT_R16_SNORM, 2 }, - { ©VertexData, true, DXGI_FORMAT_R16G16_SNORM, 4 }, - { ©VertexData, false, DXGI_FORMAT_R16G16B16A16_SNORM, 8 }, - { ©VertexData, true, DXGI_FORMAT_R16G16B16A16_SNORM, 8 }, - }, - }, - { // GL_UNSIGNED_SHORT - { // unnormalized - { ©ToFloatVertexData, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©VertexData, true, DXGI_FORMAT_R16_UNORM, 2 }, - { ©VertexData, true, DXGI_FORMAT_R16G16_UNORM, 4 }, - { ©VertexData, false, DXGI_FORMAT_R16G16B16A16_UNORM, 8 }, - { ©VertexData, true, DXGI_FORMAT_R16G16B16A16_UNORM, 8 }, - }, - }, - { // GL_FIXED - { // unnormalized - { ©FixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©FixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©FixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©FixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©FixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©FixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©FixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©FixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - }, - { // GL_FLOAT - { // unnormalized - { ©VertexData, true, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©VertexData, true, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©VertexData, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©VertexData, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©VertexData, true, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©VertexData, true, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©VertexData, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©VertexData, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - }, -}; - -const VertexBuffer11::VertexConverter &VertexBuffer11::getVertexConversion(const gl::VertexAttribute &attribute) -{ - unsigned int typeIndex = 0; - switch (attribute.mType) - { - case GL_BYTE: typeIndex = 0; break; - case GL_UNSIGNED_BYTE: typeIndex = 1; break; - case GL_SHORT: typeIndex = 2; break; - case GL_UNSIGNED_SHORT: typeIndex = 3; break; - case GL_FIXED: typeIndex = 4; break; - case GL_FLOAT: typeIndex = 5; break; - default: UNREACHABLE(); break; - } - - return mPossibleTranslations[typeIndex][attribute.mNormalized ? 1 : 0][attribute.mSize - 1]; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.h deleted file mode 100644 index eceb426e82..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.h +++ /dev/null @@ -1,74 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexBuffer11.h: Defines the D3D11 VertexBuffer implementation. - -#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ -#define LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ - -#include "libGLESv2/renderer/VertexBuffer.h" - -namespace rx -{ -class Renderer11; - -class VertexBuffer11 : public VertexBuffer -{ - public: - explicit VertexBuffer11(rx::Renderer11 *const renderer); - virtual ~VertexBuffer11(); - - virtual bool initialize(unsigned int size, bool dynamicUsage); - - static VertexBuffer11 *makeVertexBuffer11(VertexBuffer *vetexBuffer); - - virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, - unsigned int offset); - virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset); - - virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, - unsigned int *outSpaceRequired) const; - - virtual bool requiresConversion(const gl::VertexAttribute &attrib) const; - - virtual unsigned int getBufferSize() const; - virtual bool setBufferSize(unsigned int size); - virtual bool discard(); - - unsigned int getVertexSize(const gl::VertexAttribute &attrib) const; - DXGI_FORMAT getDXGIFormat(const gl::VertexAttribute &attrib) const; - - ID3D11Buffer *getBuffer() const; - - private: - DISALLOW_COPY_AND_ASSIGN(VertexBuffer11); - - rx::Renderer11 *const mRenderer; - - ID3D11Buffer *mBuffer; - unsigned int mBufferSize; - bool mDynamicUsage; - - typedef void (*VertexConversionFunction)(const void *, unsigned int, unsigned int, void *); - struct VertexConverter - { - VertexConversionFunction conversionFunc; - bool identity; - DXGI_FORMAT dxgiFormat; - unsigned int outputElementSize; - }; - - enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; - - // This table is used to generate mAttributeTypes. - static const VertexConverter mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1] - - static const VertexConverter &getVertexConversion(const gl::VertexAttribute &attribute); -}; - -} - -#endif // LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp deleted file mode 100644 index b017b3af33..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp +++ /dev/null @@ -1,530 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation. - -#include "libGLESv2/renderer/VertexBuffer9.h" -#include "libGLESv2/renderer/vertexconversion.h" -#include "libGLESv2/renderer/BufferStorage.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/renderer/Renderer9.h" - -#include "libGLESv2/Buffer.h" - -namespace rx -{ - -bool VertexBuffer9::mTranslationsInitialized = false; -VertexBuffer9::FormatConverter VertexBuffer9::mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; - -VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer) -{ - mVertexBuffer = NULL; - mBufferSize = 0; - mDynamicUsage = false; - - if (!mTranslationsInitialized) - { - initializeTranslations(renderer->getCapsDeclTypes()); - mTranslationsInitialized = true; - } -} - -VertexBuffer9::~VertexBuffer9() -{ - if (mVertexBuffer) - { - mVertexBuffer->Release(); - mVertexBuffer = NULL; - } -} - -bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) -{ - if (mVertexBuffer) - { - mVertexBuffer->Release(); - mVertexBuffer = NULL; - } - - updateSerial(); - - if (size > 0) - { - DWORD flags = D3DUSAGE_WRITEONLY; - if (dynamicUsage) - { - flags |= D3DUSAGE_DYNAMIC; - } - - HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer); - - if (FAILED(result)) - { - ERR("Out of memory allocating a vertex buffer of size %lu.", size); - return false; - } - } - - mBufferSize = size; - mDynamicUsage = dynamicUsage; - return true; -} - -VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer)); - return static_cast(vertexBuffer); -} - -bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, - GLsizei instances, unsigned int offset) -{ - if (mVertexBuffer) - { - gl::Buffer *buffer = attrib.mBoundBuffer.get(); - - int inputStride = attrib.stride(); - int elementSize = attrib.typeSize(); - const FormatConverter &converter = formatConverter(attrib); - - DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; - - void *mapPtr = NULL; - - unsigned int mapSize; - if (!spaceRequired(attrib, count, instances, &mapSize)) - { - return false; - } - - HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags); - - if (FAILED(result)) - { - ERR("Lock failed with error 0x%08x", result); - return false; - } - - const char *input = NULL; - if (buffer) - { - BufferStorage *storage = buffer->getStorage(); - input = static_cast(storage->getData()) + static_cast(attrib.mOffset); - } - else - { - input = static_cast(attrib.mPointer); - } - - if (instances == 0 || attrib.mDivisor == 0) - { - input += inputStride * start; - } - - if (converter.identity && inputStride == elementSize) - { - memcpy(mapPtr, input, count * inputStride); - } - else - { - converter.convertArray(input, inputStride, count, mapPtr); - } - - mVertexBuffer->Unlock(); - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -bool VertexBuffer9::storeRawData(const void* data, unsigned int size, unsigned int offset) -{ - if (mVertexBuffer) - { - DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; - - void *mapPtr = NULL; - HRESULT result = mVertexBuffer->Lock(offset, size, &mapPtr, lockFlags); - - if (FAILED(result)) - { - ERR("Lock failed with error 0x%08x", result); - return false; - } - - memcpy(mapPtr, data, size); - - mVertexBuffer->Unlock(); - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, - unsigned int *outSpaceRequired) const -{ - return spaceRequired(attrib, count, instances, outSpaceRequired); -} - -bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const -{ - return formatConverter(attrib).identity; -} - -unsigned int VertexBuffer9::getVertexSize(const gl::VertexAttribute &attrib) const -{ - unsigned int spaceRequired; - return getSpaceRequired(attrib, 1, 0, &spaceRequired) ? spaceRequired : 0; -} - -D3DDECLTYPE VertexBuffer9::getDeclType(const gl::VertexAttribute &attrib) const -{ - return formatConverter(attrib).d3dDeclType; -} - -unsigned int VertexBuffer9::getBufferSize() const -{ - return mBufferSize; -} - -bool VertexBuffer9::setBufferSize(unsigned int size) -{ - if (size > mBufferSize) - { - return initialize(size, mDynamicUsage); - } - else - { - return true; - } -} - -bool VertexBuffer9::discard() -{ - if (mVertexBuffer) - { - void *dummy; - HRESULT result; - - result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); - if (FAILED(result)) - { - ERR("Discard lock failed with error 0x%08x", result); - return false; - } - - result = mVertexBuffer->Unlock(); - if (FAILED(result)) - { - ERR("Discard unlock failed with error 0x%08x", result); - return false; - } - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const -{ - return mVertexBuffer; -} - -// 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 : NoWiden { }; -template struct WidenRule : WidenToEven { }; -template struct WidenRule : WidenToEven { }; -template struct WidenRule : WidenToFour { }; -template struct WidenRule : WidenToFour { }; -template struct WidenRule : 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 : Cast::type, typename D3DToCType::type> { }; - -// All conversions from normalized types to float use the Normalize operator. -template struct ConversionRule : Normalize::type> { }; - -// Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules. -template <> struct ConversionRule : FixedToFloat { }; -template <> struct ConversionRule : 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 : NormalizedDefaultValues { }; -template struct DefaultVertexValuesStage2 : SimpleDefaultValues { }; - -// Work out the default value rule for a D3D type (expressed as the C type) and -template struct DefaultVertexValues : DefaultVertexValuesStage2 { }; -template struct DefaultVertexValues : 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 - : 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 }; -}; - -// Initialize 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) }, \ - } - -#define TRANSLATIONS_FOR_TYPE_NO_NORM(type) \ - { \ - { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ - { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ - } - -const VertexBuffer9::TranslationDescription VertexBuffer9::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1] -{ - TRANSLATIONS_FOR_TYPE(GL_BYTE), - TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE), - TRANSLATIONS_FOR_TYPE(GL_SHORT), - TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT), - TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED), - TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT) -}; - -void VertexBuffer9::initializeTranslations(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) - { - mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion; - } - else - { - mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion; - } - } - } - } -} - -unsigned int VertexBuffer9::typeIndex(GLenum type) -{ - 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; - } -} - -const VertexBuffer9::FormatConverter &VertexBuffer9::formatConverter(const gl::VertexAttribute &attribute) -{ - return mFormatConverters[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1]; -} - -bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, - unsigned int *outSpaceRequired) -{ - unsigned int elementSize = formatConverter(attrib).outputElementSize; - - if (attrib.mArrayEnabled) - { - unsigned int elementCount = 0; - if (instances == 0 || attrib.mDivisor == 0) - { - elementCount = count; - } - else - { - if (static_cast(instances) < std::numeric_limits::max() - (attrib.mDivisor - 1)) - { - // Round up - elementCount = (static_cast(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor; - } - else - { - elementCount = static_cast(instances) / attrib.mDivisor; - } - } - - if (elementSize <= std::numeric_limits::max() / elementCount) - { - if (outSpaceRequired) - { - *outSpaceRequired = elementSize * elementCount; - } - return true; - } - else - { - return false; - } - } - else - { - const unsigned int elementSize = 4; - if (outSpaceRequired) - { - *outSpaceRequired = elementSize * 4; - } - return true; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h deleted file mode 100644 index 2f88117bda..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h +++ /dev/null @@ -1,91 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexBuffer9.h: Defines the D3D9 VertexBuffer implementation. - -#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ -#define LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ - -#include "libGLESv2/renderer/VertexBuffer.h" - -namespace rx -{ -class Renderer9; - -class VertexBuffer9 : public VertexBuffer -{ - public: - explicit VertexBuffer9(rx::Renderer9 *const renderer); - virtual ~VertexBuffer9(); - - virtual bool initialize(unsigned int size, bool dynamicUsage); - - static VertexBuffer9 *makeVertexBuffer9(VertexBuffer *vertexBuffer); - - virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, - unsigned int offset); - virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset); - - virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const; - - virtual bool requiresConversion(const gl::VertexAttribute &attrib) const; - - unsigned int getVertexSize(const gl::VertexAttribute &attrib) const; - D3DDECLTYPE getDeclType(const gl::VertexAttribute &attrib) const; - - virtual unsigned int getBufferSize() const; - virtual bool setBufferSize(unsigned int size); - virtual bool discard(); - - IDirect3DVertexBuffer9 *getBuffer() const; - - private: - DISALLOW_COPY_AND_ASSIGN(VertexBuffer9); - - rx::Renderer9 *const mRenderer; - - IDirect3DVertexBuffer9 *mVertexBuffer; - unsigned int mBufferSize; - bool mDynamicUsage; - - // Attribute format conversion - enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; - - 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; - }; - - static bool mTranslationsInitialized; - static void initializeTranslations(DWORD declTypes); - - // [GL types as enumerated by typeIndex()][normalized][size - 1] - static FormatConverter mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; - - struct TranslationDescription - { - DWORD capsFlag; - FormatConverter preferredConversion; - FormatConverter fallbackConversion; - }; - - // This table is used to generate mFormatConverters. - // [GL types as enumerated by typeIndex()][normalized][size - 1] - static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; - - static unsigned int typeIndex(GLenum type); - static const FormatConverter &formatConverter(const gl::VertexAttribute &attribute); - - static bool spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, - unsigned int *outSpaceRequired); -}; - -} - -#endif // LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp index 7ff5171fca..8034aed8c9 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp @@ -266,6 +266,10 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], return GL_OUT_OF_MEMORY; } + mCurrentValue[i][0] = attribs[i].mCurrentValue[0]; + mCurrentValue[i][1] = attribs[i].mCurrentValue[1]; + mCurrentValue[i][2] = attribs[i].mCurrentValue[2]; + mCurrentValue[i][3] = attribs[i].mCurrentValue[3]; mCurrentValueOffsets[i] = streamOffset; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp deleted file mode 100644 index 9b83a6476e..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp +++ /dev/null @@ -1,217 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations. - -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/renderer/VertexBuffer9.h" -#include "libGLESv2/renderer/VertexDeclarationCache.h" - -namespace rx -{ - -VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0) -{ - for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) - { - mVertexDeclCache[i].vertexDeclaration = NULL; - mVertexDeclCache[i].lruCount = 0; - } - - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mAppliedVBs[i].serial = 0; - } - - mLastSetVDecl = NULL; - mInstancingEnabled = true; -} - -VertexDeclarationCache::~VertexDeclarationCache() -{ - for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) - { - if (mVertexDeclCache[i].vertexDeclaration) - { - mVertexDeclCache[i].vertexDeclaration->Release(); - } - } -} - -GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw) -{ - *repeatDraw = 1; - - int indexedAttribute = gl::MAX_VERTEX_ATTRIBS; - int instancedAttribute = gl::MAX_VERTEX_ATTRIBS; - - if (instances > 0) - { - // Find an indexed attribute to be mapped to D3D stream 0 - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - if (attributes[i].active) - { - if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor == 0) - { - indexedAttribute = i; - } - else if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor != 0) - { - instancedAttribute = i; - } - if (indexedAttribute != gl::MAX_VERTEX_ATTRIBS && instancedAttribute != gl::MAX_VERTEX_ATTRIBS) - break; // Found both an indexed and instanced attribute - } - } - - if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS) - { - return GL_INVALID_OPERATION; - } - } - - D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1]; - D3DVERTEXELEMENT9 *element = &elements[0]; - - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - if (attributes[i].active) - { - // Directly binding the storage buffer is not supported for d3d9 - ASSERT(attributes[i].storage == NULL); - - int stream = i; - - if (instances > 0) - { - // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced. - if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS) - { - *repeatDraw = instances; - } - else - { - if (i == indexedAttribute) - { - stream = 0; - } - else if (i == 0) - { - stream = indexedAttribute; - } - - UINT frequency = 1; - - if (attributes[i].divisor == 0) - { - frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances; - } - else - { - frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor; - } - - device->SetStreamSourceFreq(stream, frequency); - mInstancingEnabled = true; - } - } - - VertexBuffer9 *vertexBuffer = VertexBuffer9::makeVertexBuffer9(attributes[i].vertexBuffer); - - if (mAppliedVBs[stream].serial != attributes[i].serial || - mAppliedVBs[stream].stride != attributes[i].stride || - mAppliedVBs[stream].offset != attributes[i].offset) - { - device->SetStreamSource(stream, vertexBuffer->getBuffer(), attributes[i].offset, attributes[i].stride); - mAppliedVBs[stream].serial = attributes[i].serial; - mAppliedVBs[stream].stride = attributes[i].stride; - mAppliedVBs[stream].offset = attributes[i].offset; - } - - element->Stream = stream; - element->Offset = 0; - element->Type = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDeclType(*attributes[i].attribute) : D3DDECLTYPE_FLOAT4; - element->Method = D3DDECLMETHOD_DEFAULT; - element->Usage = D3DDECLUSAGE_TEXCOORD; - element->UsageIndex = programBinary->getSemanticIndex(i); - element++; - } - } - - if (instances == 0 || instancedAttribute == gl::MAX_VERTEX_ATTRIBS) - { - if (mInstancingEnabled) - { - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - device->SetStreamSourceFreq(i, 1); - } - - mInstancingEnabled = false; - } - } - - static const D3DVERTEXELEMENT9 end = D3DDECL_END(); - *(element++) = end; - - for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) - { - VertexDeclCacheEntry *entry = &mVertexDeclCache[i]; - if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration) - { - entry->lruCount = ++mMaxLru; - if(entry->vertexDeclaration != mLastSetVDecl) - { - device->SetVertexDeclaration(entry->vertexDeclaration); - mLastSetVDecl = entry->vertexDeclaration; - } - - return GL_NO_ERROR; - } - } - - VertexDeclCacheEntry *lastCache = mVertexDeclCache; - - for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) - { - if (mVertexDeclCache[i].lruCount < lastCache->lruCount) - { - lastCache = &mVertexDeclCache[i]; - } - } - - if (lastCache->vertexDeclaration != NULL) - { - lastCache->vertexDeclaration->Release(); - lastCache->vertexDeclaration = NULL; - // mLastSetVDecl is set to the replacement, so we don't have to worry - // about it. - } - - memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)); - device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration); - device->SetVertexDeclaration(lastCache->vertexDeclaration); - mLastSetVDecl = lastCache->vertexDeclaration; - lastCache->lruCount = ++mMaxLru; - - return GL_NO_ERROR; -} - -void VertexDeclarationCache::markStateDirty() -{ - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mAppliedVBs[i].serial = 0; - } - - mLastSetVDecl = NULL; - mInstancingEnabled = true; // Forces it to be disabled when not used -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDeclarationCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDeclarationCache.h deleted file mode 100644 index 3fc024a9ba..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDeclarationCache.h +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexDeclarationCache.h: Defines a helper class to construct and cache vertex declarations. - -#ifndef LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ -#define LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ - -#include "libGLESv2/renderer/VertexDataManager.h" - -namespace gl -{ -class VertexDataManager; -} - -namespace rx -{ - -class VertexDeclarationCache -{ - public: - VertexDeclarationCache(); - ~VertexDeclarationCache(); - - GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw); - - void markStateDirty(); - - private: - UINT mMaxLru; - - enum { NUM_VERTEX_DECL_CACHE_ENTRIES = 32 }; - - struct VBData - { - unsigned int serial; - unsigned int stride; - unsigned int offset; - }; - - VBData mAppliedVBs[gl::MAX_VERTEX_ATTRIBS]; - IDirect3DVertexDeclaration9 *mLastSetVDecl; - bool mInstancingEnabled; - - struct VertexDeclCacheEntry - { - D3DVERTEXELEMENT9 cachedElements[gl::MAX_VERTEX_ATTRIBS + 1]; - UINT lruCount; - IDirect3DVertexDeclaration9 *vertexDeclaration; - } mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES]; -}; - -} - -#endif // LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp new file mode 100644 index 0000000000..31d5b8b886 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp @@ -0,0 +1,366 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferStorage11.cpp Defines the BufferStorage11 class. + +#include "libGLESv2/renderer/d3d11/BufferStorage11.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" + +namespace rx +{ + +BufferStorage11::BufferStorage11(Renderer11 *renderer) +{ + mRenderer = renderer; + + mStagingBuffer = NULL; + mStagingBufferSize = 0; + + mSize = 0; + + mResolvedData = NULL; + mResolvedDataSize = 0; + mResolvedDataValid = false; + + mReadUsageCount = 0; + mWriteUsageCount = 0; +} + +BufferStorage11::~BufferStorage11() +{ + SafeRelease(mStagingBuffer); + + if (mResolvedData) + { + free(mResolvedData); + mResolvedData = NULL; + } + + for (auto it = mDirectBuffers.begin(); it != mDirectBuffers.end(); it++) + { + SafeDelete(it->second); + } +} + +BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage) +{ + ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage)); + return static_cast(bufferStorage); +} + +void *BufferStorage11::getData() +{ + ASSERT(mStagingBuffer); + + if (!mResolvedDataValid) + { + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + HRESULT result; + + if (!mResolvedData || mResolvedDataSize < mStagingBufferSize) + { + free(mResolvedData); + mResolvedData = malloc(mSize); + mResolvedDataSize = mSize; + } + + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource); + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); + } + + memcpy(mResolvedData, mappedResource.pData, mSize); + + context->Unmap(mStagingBuffer, 0); + + mResolvedDataValid = true; + } + + mReadUsageCount = 0; + + return mResolvedData; +} + +void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset) +{ + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + HRESULT result; + + const unsigned int requiredStagingBufferSize = size + offset; + const bool createStagingBuffer = !mStagingBuffer || mStagingBufferSize < requiredStagingBufferSize; + + if (createStagingBuffer) + { + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = requiredStagingBufferSize; + bufferDesc.Usage = D3D11_USAGE_STAGING; + bufferDesc.BindFlags = 0; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + HRESULT result; + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + ID3D11Buffer *newStagingBuffer; + + if (data && offset == 0) + { + D3D11_SUBRESOURCE_DATA initialData; + initialData.pSysMem = data; + initialData.SysMemPitch = requiredStagingBufferSize; + initialData.SysMemSlicePitch = 0; + + result = device->CreateBuffer(&bufferDesc, &initialData, &newStagingBuffer); + } + else + { + result = device->CreateBuffer(&bufferDesc, NULL, &newStagingBuffer); + } + + if (FAILED(result)) + { + mStagingBufferSize = 0; + return gl::error(GL_OUT_OF_MEMORY); + } + + mStagingBufferSize = requiredStagingBufferSize; + + if (mStagingBuffer && offset > 0) + { + // If offset is greater than zero and the buffer is non-null, need to preserve the data from + // the old buffer up to offset + D3D11_BOX srcBox; + srcBox.left = 0; + srcBox.right = std::min(offset, requiredStagingBufferSize); + srcBox.top = 0; + srcBox.bottom = 1; + srcBox.front = 0; + srcBox.back = 1; + + context->CopySubresourceRegion(newStagingBuffer, 0, 0, 0, 0, mStagingBuffer, 0, &srcBox); + } + + SafeRelease(mStagingBuffer); + mStagingBuffer = newStagingBuffer; + } + + if (data && (offset != 0 || !createStagingBuffer)) + { + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource); + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY); + } + + unsigned char *offsetBufferPointer = reinterpret_cast(mappedResource.pData) + offset; + memcpy(offsetBufferPointer, data, size); + + context->Unmap(mStagingBuffer, 0); + } + + for (auto it = mDirectBuffers.begin(); it != mDirectBuffers.end(); it++) + { + it->second->markDirty(); + } + + mSize = std::max(mSize, requiredStagingBufferSize); + mWriteUsageCount = 0; + + mResolvedDataValid = false; +} + +void BufferStorage11::copyData(BufferStorage* sourceStorage, unsigned int size, + unsigned int sourceOffset, unsigned int destOffset) +{ + BufferStorage11* source = makeBufferStorage11(sourceStorage); + if (source) + { + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + D3D11_BOX srcBox; + srcBox.left = sourceOffset; + srcBox.right = sourceOffset + size; + srcBox.top = 0; + srcBox.bottom = 1; + srcBox.front = 0; + srcBox.back = 1; + + ASSERT(mStagingBuffer && source->mStagingBuffer); + context->CopySubresourceRegion(mStagingBuffer, 0, destOffset, 0, 0, source->mStagingBuffer, 0, &srcBox); + } +} + +void BufferStorage11::clear() +{ + mResolvedDataValid = false; + mSize = 0; +} + +unsigned int BufferStorage11::getSize() const +{ + return mSize; +} + +bool BufferStorage11::supportsDirectBinding() const +{ + return true; +} + +void BufferStorage11::markBufferUsage() +{ + mReadUsageCount++; + mWriteUsageCount++; + + const unsigned int usageLimit = 5; + + if (mReadUsageCount > usageLimit && mResolvedData) + { + free(mResolvedData); + mResolvedData = NULL; + mResolvedDataSize = 0; + mResolvedDataValid = false; + } +} + +ID3D11Buffer *BufferStorage11::getBuffer(BufferUsage usage) +{ + markBufferUsage(); + + DirectBufferStorage11 *directBuffer = NULL; + + auto directBufferIt = mDirectBuffers.find(usage); + if (directBufferIt != mDirectBuffers.end()) + { + directBuffer = directBufferIt->second; + } + + if (directBuffer) + { + if (directBuffer->isDirty()) + { + // if updateFromStagingBuffer returns true, the D3D buffer has been recreated + // and we should update our serial + if (directBuffer->updateFromStagingBuffer(mStagingBuffer, mSize, 0)) + { + updateSerial(); + } + } + } + else + { + // buffer is not allocated, create it + directBuffer = new DirectBufferStorage11(mRenderer, usage); + directBuffer->updateFromStagingBuffer(mStagingBuffer, mSize, 0); + + mDirectBuffers.insert(std::make_pair(usage, directBuffer)); + updateSerial(); + } + + return directBuffer->getD3DBuffer(); +} + +DirectBufferStorage11::DirectBufferStorage11(Renderer11 *renderer, BufferUsage usage) + : mRenderer(renderer), + mUsage(usage), + mDirectBuffer(NULL), + mBufferSize(0), + mDirty(false) +{ +} + +DirectBufferStorage11::~DirectBufferStorage11() +{ + SafeRelease(mDirectBuffer); +} + +BufferUsage DirectBufferStorage11::getUsage() const +{ + return mUsage; +} + +// Returns true if it recreates the direct buffer +bool DirectBufferStorage11::updateFromStagingBuffer(ID3D11Buffer *stagingBuffer, size_t size, size_t offset) +{ + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + // unused for now + ASSERT(offset == 0); + + unsigned int requiredBufferSize = size + offset; + bool createBuffer = !mDirectBuffer || mBufferSize < requiredBufferSize; + + // (Re)initialize D3D buffer if needed + if (createBuffer) + { + D3D11_BUFFER_DESC bufferDesc; + fillBufferDesc(&bufferDesc, mRenderer, mUsage, requiredBufferSize); + + ID3D11Buffer *newBuffer; + HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer); + + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY, false); + } + + // No longer need the old buffer + SafeRelease(mDirectBuffer); + mDirectBuffer = newBuffer; + + mBufferSize = bufferDesc.ByteWidth; + } + + // Copy data via staging buffer + D3D11_BOX srcBox; + srcBox.left = 0; + srcBox.right = size; + srcBox.top = 0; + srcBox.bottom = 1; + srcBox.front = 0; + srcBox.back = 1; + + context->CopySubresourceRegion(mDirectBuffer, 0, offset, 0, 0, stagingBuffer, 0, &srcBox); + + mDirty = false; + + return createBuffer; +} + +void DirectBufferStorage11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize) +{ + bufferDesc->ByteWidth = bufferSize; + bufferDesc->MiscFlags = 0; + bufferDesc->StructureByteStride = 0; + + switch (usage) + { + case BUFFER_USAGE_VERTEX: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_INDEX: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc->CPUAccessFlags = 0; + break; + + default: + UNREACHABLE(); + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h new file mode 100644 index 0000000000..a6afafe1b4 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h @@ -0,0 +1,92 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferStorage11.h Defines the BufferStorage11 class. + +#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ +#define LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ + +#include "libGLESv2/renderer/BufferStorage.h" + +namespace rx +{ +class Renderer; +class Renderer11; +class DirectBufferStorage11; + +enum BufferUsage +{ + BUFFER_USAGE_VERTEX, + BUFFER_USAGE_INDEX, +}; + +class BufferStorage11 : public BufferStorage +{ + public: + explicit BufferStorage11(Renderer11 *renderer); + virtual ~BufferStorage11(); + + static BufferStorage11 *makeBufferStorage11(BufferStorage *bufferStorage); + + virtual void *getData(); + virtual void setData(const void* data, unsigned int size, unsigned int offset); + virtual void copyData(BufferStorage* sourceStorage, unsigned int size, + unsigned int sourceOffset, unsigned int destOffset); + virtual void clear(); + virtual unsigned int getSize() const; + virtual bool supportsDirectBinding() const; + + ID3D11Buffer *getBuffer(BufferUsage usage); + + private: + Renderer11 *mRenderer; + + ID3D11Buffer *mStagingBuffer; + unsigned int mStagingBufferSize; + + std::map mDirectBuffers; + + unsigned int mSize; + + void *mResolvedData; + unsigned int mResolvedDataSize; + bool mResolvedDataValid; + + unsigned int mReadUsageCount; + unsigned int mWriteUsageCount; + + void markBufferUsage(); +}; + +// Each instance of BufferStorageD3DBuffer11 is specialized for a class of D3D binding points +// - vertex buffers +// - index buffers +class DirectBufferStorage11 +{ + public: + DirectBufferStorage11(Renderer11 *renderer, BufferUsage usage); + ~DirectBufferStorage11(); + + BufferUsage getUsage() const; + bool updateFromStagingBuffer(ID3D11Buffer *stagingBuffer, size_t size, size_t offset); + + ID3D11Buffer *getD3DBuffer() { return mDirectBuffer; } + bool isDirty() const { return mDirty; } + void markDirty() { mDirty = true; } + + private: + Renderer11 *mRenderer; + const BufferUsage mUsage; + ID3D11Buffer *mDirectBuffer; + size_t mBufferSize; + bool mDirty; + + static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize); +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp new file mode 100644 index 0000000000..2a7d4d43ef --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp @@ -0,0 +1,134 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Fence11.cpp: Defines the rx::Fence11 class which implements rx::FenceImpl. + +#include "libGLESv2/renderer/d3d11/Fence11.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" + +namespace rx +{ + +Fence11::Fence11(rx::Renderer11 *renderer) +{ + mRenderer = renderer; + mQuery = NULL; +} + +Fence11::~Fence11() +{ + if (mQuery) + { + mQuery->Release(); + mQuery = NULL; + } +} + +GLboolean Fence11::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 Fence11::setFence(GLenum condition) +{ + if (!mQuery) + { + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = D3D11_QUERY_EVENT; + queryDesc.MiscFlags = 0; + + if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery))) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + mRenderer->getDeviceContext()->End(mQuery); + + setCondition(condition); + setStatus(GL_FALSE); +} + +GLboolean Fence11::testFence() +{ + if (mQuery == NULL) + { + return gl::error(GL_INVALID_OPERATION, GL_TRUE); + } + + HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, 0); + + if (mRenderer->isDeviceLost()) + { + return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); + } + + ASSERT(result == S_OK || result == S_FALSE); + setStatus(result == S_OK); + return getStatus(); +} + +void Fence11::finishFence() +{ + if (mQuery == NULL) + { + return gl::error(GL_INVALID_OPERATION); + } + + while (!testFence()) + { + Sleep(0); + } +} + +void Fence11::getFenceiv(GLenum pname, GLint *params) +{ + if (mQuery == NULL) + { + return gl::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 (getStatus()) + { + params[0] = GL_TRUE; + return; + } + + HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); + + if (mRenderer->isDeviceLost()) + { + params[0] = GL_TRUE; + return gl::error(GL_OUT_OF_MEMORY); + } + + ASSERT(result == S_OK || result == S_FALSE); + setStatus(result == S_OK); + params[0] = getStatus(); + + break; + } + case GL_FENCE_CONDITION_NV: + params[0] = getCondition(); + break; + default: + return gl::error(GL_INVALID_ENUM); + break; + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.h new file mode 100644 index 0000000000..a5398bca14 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Fence11.h: Defines the rx::Fence11 class which implements rx::FenceImpl. + +#ifndef LIBGLESV2_RENDERER_Fence11_H_ +#define LIBGLESV2_RENDERER_Fence11_H_ + +#include "libGLESv2/renderer/FenceImpl.h" + +namespace rx +{ +class Renderer11; + +class Fence11 : public FenceImpl +{ + public: + explicit Fence11(rx::Renderer11 *renderer); + virtual ~Fence11(); + + GLboolean isFence(); + void setFence(GLenum condition); + GLboolean testFence(); + void finishFence(); + void getFenceiv(GLenum pname, GLint *params); + + private: + DISALLOW_COPY_AND_ASSIGN(Fence11); + + rx::Renderer11 *mRenderer; + ID3D11Query *mQuery; +}; + +} + +#endif // LIBGLESV2_RENDERER_FENCE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp new file mode 100644 index 0000000000..5d039a35e8 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp @@ -0,0 +1,498 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image11.h: Implements the rx::Image11 class, which acts as the interface to +// the actual underlying resources of a Texture + +#include "libGLESv2/renderer/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d11/Image11.h" +#include "libGLESv2/renderer/d3d11/TextureStorage11.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" + +#include "libGLESv2/main.h" +#include "libGLESv2/utilities.h" +#include "libGLESv2/renderer/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/generatemip.h" + +namespace rx +{ + +Image11::Image11() +{ + mStagingTexture = NULL; + mRenderer = NULL; + mDXGIFormat = DXGI_FORMAT_UNKNOWN; +} + +Image11::~Image11() +{ + if (mStagingTexture) + { + mStagingTexture->Release(); + } +} + +Image11 *Image11::makeImage11(Image *img) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::Image11*, img)); + return static_cast(img); +} + +void Image11::generateMipmap(Image11 *dest, Image11 *src) +{ + ASSERT(src->getDXGIFormat() == dest->getDXGIFormat()); + ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth()); + ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight()); + + D3D11_MAPPED_SUBRESOURCE destMapped, srcMapped; + dest->map(D3D11_MAP_WRITE, &destMapped); + src->map(D3D11_MAP_READ, &srcMapped); + + const unsigned char *sourceData = reinterpret_cast(srcMapped.pData); + unsigned char *destData = reinterpret_cast(destMapped.pData); + + if (sourceData && destData) + { + switch (src->getDXGIFormat()) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_A8_UNORM: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R8_UNORM: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R32G32B32A32_FLOAT: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R32G32B32_FLOAT: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R16G16B16A16_FLOAT: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R8G8_UNORM: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R16_FLOAT: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R16G16_FLOAT: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R32_FLOAT: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + case DXGI_FORMAT_R32G32_FLOAT: + GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); + break; + default: + UNREACHABLE(); + break; + } + + dest->unmap(); + src->unmap(); + } + + dest->markDirty(); +} + +static bool FormatRequiresInitialization(DXGI_FORMAT dxgiFormat, GLenum internalFormat) +{ + return (dxgiFormat == DXGI_FORMAT_R8G8B8A8_UNORM && gl::GetAlphaSize(internalFormat) == 0) || + (dxgiFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && gl::GetAlphaSize(internalFormat) == 0); +} + +bool Image11::isDirty() const +{ + return ((mStagingTexture || FormatRequiresInitialization(mDXGIFormat, mInternalFormat)) && mDirty); +} + +bool Image11::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); + return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, width, height); +} + +bool Image11::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); + return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, face, xoffset, yoffset, width, height); +} + +bool Image11::redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) +{ + if (mWidth != width || + mHeight != height || + mInternalFormat != internalformat || + forceRelease) + { + mRenderer = Renderer11::makeRenderer11(renderer); + + mWidth = width; + mHeight = height; + mInternalFormat = internalformat; + // compute the d3d format that will be used + mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel()); + mActualFormat = d3d11_gl::ConvertTextureInternalFormat(mDXGIFormat); + + if (mStagingTexture) + { + mStagingTexture->Release(); + mStagingTexture = NULL; + } + + return true; + } + + return false; +} + +bool Image11::isRenderableFormat() const +{ + return TextureStorage11::IsTextureFormatRenderable(mDXGIFormat); +} + +DXGI_FORMAT Image11::getDXGIFormat() const +{ + // this should only happen if the image hasn't been redefined first + // which would be a bug by the caller + ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN); + + return mDXGIFormat; +} + +// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input +// into the target pixel rectangle. +void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLint unpackAlignment, const void *input) +{ + D3D11_MAPPED_SUBRESOURCE mappedImage; + HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); + if (FAILED(result)) + { + ERR("Could not map image for loading."); + return; + } + + GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment); + size_t pixelSize = d3d11::ComputePixelSizeBits(mDXGIFormat) / 8; + void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + (yoffset * mappedImage.RowPitch + xoffset * pixelSize)); + + switch (mInternalFormat) + { + case GL_ALPHA8_EXT: + if (mRenderer->getFeatureLevel() >= D3D_FEATURE_LEVEL_10_0) + loadAlphaDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + else + loadAlphaDataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_LUMINANCE8_EXT: + loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false); + break; + case GL_ALPHA32F_EXT: + loadAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_LUMINANCE32F_EXT: + loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_ALPHA16F_EXT: + loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_LUMINANCE16F_EXT: + loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_LUMINANCE8_ALPHA8_EXT: + loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false); + break; + case GL_LUMINANCE_ALPHA32F_EXT: + loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_LUMINANCE_ALPHA16F_EXT: + loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGB8_OES: + loadRGBUByteDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGB565: + loadRGB565DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGBA8_OES: + loadRGBAUByteDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGBA4: + loadRGBA4444DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGB5_A1: + loadRGBA5551DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_BGRA8_EXT: + loadBGRADataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGB32F_EXT: + loadRGBFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGB16F_EXT: + loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGBA32F_EXT: + loadRGBAFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_RGBA16F_EXT: + loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + default: UNREACHABLE(); + } + + unmap(); +} + +void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + const void *input) +{ + ASSERT(xoffset % 4 == 0); + ASSERT(yoffset % 4 == 0); + + D3D11_MAPPED_SUBRESOURCE mappedImage; + HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); + if (FAILED(result)) + { + ERR("Could not map image for loading."); + return; + } + + // Size computation assumes a 4x4 block compressed texture format + size_t blockSize = d3d11::ComputeBlockSizeBits(mDXGIFormat) / 8; + void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + ((yoffset / 4) * mappedImage.RowPitch + (xoffset / 4) * blockSize)); + + GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat); + GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat); + int rows = inputSize / inputPitch; + for (int i = 0; i < rows; ++i) + { + memcpy((void*)((BYTE*)offsetMappedData + i * mappedImage.RowPitch), (void*)((BYTE*)input + i * inputPitch), inputPitch); + } + + unmap(); +} + +void Image11::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + gl::Renderbuffer *colorbuffer = source->getReadColorbuffer(); + + if (colorbuffer && colorbuffer->getActualFormat() == (GLuint)mActualFormat) + { + // No conversion needed-- use copyback fastpath + ID3D11Texture2D *colorBufferTexture = NULL; + unsigned int subresourceIndex = 0; + + if (mRenderer->getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) + { + D3D11_TEXTURE2D_DESC textureDesc; + colorBufferTexture->GetDesc(&textureDesc); + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + ID3D11Texture2D* srcTex = NULL; + if (textureDesc.SampleDesc.Count > 1) + { + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = textureDesc.Width; + resolveDesc.Height = textureDesc.Height; + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = textureDesc.Format; + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = D3D11_USAGE_DEFAULT; + resolveDesc.BindFlags = 0; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex); + if (FAILED(result)) + { + ERR("Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result); + return; + } + + deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format); + subresourceIndex = 0; + } + else + { + srcTex = colorBufferTexture; + srcTex->AddRef(); + } + + D3D11_BOX srcBox; + srcBox.left = x; + srcBox.right = x + width; + srcBox.top = y; + srcBox.bottom = y + height; + srcBox.front = 0; + srcBox.back = 1; + + deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, 0, srcTex, subresourceIndex, &srcBox); + + srcTex->Release(); + colorBufferTexture->Release(); + } + } + else + { + // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels + D3D11_MAPPED_SUBRESOURCE mappedImage; + HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); + + // determine the offset coordinate into the destination buffer + GLsizei rowOffset = gl::ComputePixelSize(mActualFormat) * xoffset; + void *dataOffset = static_cast(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset; + + mRenderer->readPixels(source, x, y, width, height, gl::ExtractFormat(mInternalFormat), + gl::ExtractType(mInternalFormat), mappedImage.RowPitch, false, 4, dataOffset); + + unmap(); + } +} + +ID3D11Texture2D *Image11::getStagingTexture() +{ + createStagingTexture(); + + return mStagingTexture; +} + +unsigned int Image11::getStagingSubresource() +{ + createStagingTexture(); + + return mStagingSubresource; +} + +template +static void setDefaultData(ID3D11DeviceContext *deviceContext, ID3D11Texture2D *texture, UINT subresource, + GLsizei width, GLsizei height, const T (&defaultData)[N]) +{ + D3D11_MAPPED_SUBRESOURCE map; + deviceContext->Map(texture, subresource, D3D11_MAP_WRITE, 0, &map); + + unsigned char* ptr = reinterpret_cast(map.pData); + size_t pixelSize = sizeof(T) * N; + + for (GLsizei y = 0; y < height; y++) + { + for (GLsizei x = 0; x < width; x++) + { + memcpy(ptr + (y * map.RowPitch) + (x * pixelSize), defaultData, pixelSize); + } + } + + deviceContext->Unmap(texture, subresource); +} + +void Image11::createStagingTexture() +{ + if (mStagingTexture) + { + return; + } + + ID3D11Texture2D *newTexture = NULL; + int lodOffset = 1; + const DXGI_FORMAT dxgiFormat = getDXGIFormat(); + ASSERT(!d3d11::IsDepthStencilFormat(dxgiFormat)); // We should never get here for depth textures + + if (mWidth != 0 && mHeight != 0) + { + GLsizei width = mWidth; + GLsizei height = mHeight; + + // adjust size if needed for compressed textures + gl::MakeValidSize(false, d3d11::IsCompressed(dxgiFormat), &width, &height, &lodOffset); + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.MipLevels = lodOffset + 1; + desc.ArraySize = 1; + desc.Format = dxgiFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &newTexture); + + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + mStagingTexture = newTexture; + mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); + mDirty = false; + + if (mDXGIFormat == DXGI_FORMAT_R8G8B8A8_UNORM && gl::GetAlphaSize(mInternalFormat) == 0) + { + unsigned char defaultPixel[4] = { 0, 0, 0, 255 }; + setDefaultData(mRenderer->getDeviceContext(), mStagingTexture, mStagingSubresource, mWidth, mHeight, defaultPixel); + } + else if (mDXGIFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && gl::GetAlphaSize(mInternalFormat) == 0) + { + float defaultPixel[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + setDefaultData(mRenderer->getDeviceContext(), mStagingTexture, mStagingSubresource, mWidth, mHeight, defaultPixel); + } +} + +HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) +{ + createStagingTexture(); + + HRESULT result = E_FAIL; + + if (mStagingTexture) + { + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + result = deviceContext->Map(mStagingTexture, mStagingSubresource, mapType, 0, map); + + // this can fail if the device is removed (from TDR) + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + } + else if (SUCCEEDED(result)) + { + mDirty = true; + } + } + + return result; +} + +void Image11::unmap() +{ + if (mStagingTexture) + { + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + deviceContext->Unmap(mStagingTexture, mStagingSubresource); + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.h new file mode 100644 index 0000000000..11a6492dc8 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.h @@ -0,0 +1,76 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image11.h: Defines the rx::Image11 class, which acts as the interface to +// the actual underlying resources of a Texture + +#ifndef LIBGLESV2_RENDERER_IMAGE11_H_ +#define LIBGLESV2_RENDERER_IMAGE11_H_ + +#include "libGLESv2/renderer/Image.h" + +#include "common/debug.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer; +class Renderer11; +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; + +class Image11 : public Image +{ + public: + Image11(); + virtual ~Image11(); + + static Image11 *makeImage11(Image *img); + + static void generateMipmap(Image11 *dest, Image11 *src); + + virtual bool isDirty() const; + + virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + + virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease); + + virtual bool isRenderableFormat() const; + DXGI_FORMAT getDXGIFormat() const; + + virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLint unpackAlignment, const void *input); + virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + const void *input); + + virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + + protected: + HRESULT map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map); + void unmap(); + + private: + DISALLOW_COPY_AND_ASSIGN(Image11); + + ID3D11Texture2D *getStagingTexture(); + unsigned int getStagingSubresource(); + void createStagingTexture(); + + Renderer11 *mRenderer; + + DXGI_FORMAT mDXGIFormat; + ID3D11Texture2D *mStagingTexture; + unsigned int mStagingSubresource; +}; + +} + +#endif // LIBGLESV2_RENDERER_IMAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp new file mode 100644 index 0000000000..44f9976d43 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp @@ -0,0 +1,183 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation. + +#include "libGLESv2/renderer/d3d11/IndexBuffer11.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" + +namespace rx +{ + +IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) +{ + mBuffer = NULL; + mBufferSize = 0; + mDynamicUsage = false; +} + +IndexBuffer11::~IndexBuffer11() +{ + if (mBuffer) + { + mBuffer->Release(); + mBuffer = NULL; + } +} + +bool IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) +{ + if (mBuffer) + { + mBuffer->Release(); + mBuffer = NULL; + } + + updateSerial(); + + if (bufferSize > 0) + { + ID3D11Device* dxDevice = mRenderer->getDevice(); + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = bufferSize; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); + if (FAILED(result)) + { + return false; + } + } + + mBufferSize = bufferSize; + mIndexType = indexType; + mDynamicUsage = dynamic; + + return true; +} + +IndexBuffer11 *IndexBuffer11::makeIndexBuffer11(IndexBuffer *indexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer11*, indexBuffer)); + return static_cast(indexBuffer); +} + +bool IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) +{ + if (mBuffer) + { + // Check for integer overflows and out-out-bounds map requests + if (offset + size < offset || offset + size > mBufferSize) + { + ERR("Index buffer map range is not inside the buffer."); + return false; + } + + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Index buffer map failed with error 0x%08x", result); + return false; + } + + *outMappedMemory = reinterpret_cast(mappedResource.pData) + offset; + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +bool IndexBuffer11::unmapBuffer() +{ + if (mBuffer) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + dxContext->Unmap(mBuffer, 0); + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +GLenum IndexBuffer11::getIndexType() const +{ + return mIndexType; +} + +unsigned int IndexBuffer11::getBufferSize() const +{ + return mBufferSize; +} + +bool IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType) +{ + if (bufferSize > mBufferSize || indexType != mIndexType) + { + return initialize(bufferSize, indexType, mDynamicUsage); + } + else + { + return true; + } +} + +bool IndexBuffer11::discard() +{ + if (mBuffer) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Index buffer map failed with error 0x%08x", result); + return false; + } + + dxContext->Unmap(mBuffer, 0); + + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +DXGI_FORMAT IndexBuffer11::getIndexFormat() const +{ + switch (mIndexType) + { + case GL_UNSIGNED_BYTE: return DXGI_FORMAT_R16_UINT; + case GL_UNSIGNED_SHORT: return DXGI_FORMAT_R16_UINT; + case GL_UNSIGNED_INT: return DXGI_FORMAT_R32_UINT; + default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; + } +} + +ID3D11Buffer *IndexBuffer11::getBuffer() const +{ + return mBuffer; +} + +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h new file mode 100644 index 0000000000..39a61946ad --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexBuffer11.h: Defines the D3D11 IndexBuffer implementation. + +#ifndef LIBGLESV2_RENDERER_INDEXBUFFER11_H_ +#define LIBGLESV2_RENDERER_INDEXBUFFER11_H_ + +#include "libGLESv2/renderer/IndexBuffer.h" + +namespace rx +{ +class Renderer11; + +class IndexBuffer11 : public IndexBuffer +{ + public: + explicit IndexBuffer11(Renderer11 *const renderer); + virtual ~IndexBuffer11(); + + virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); + + static IndexBuffer11 *makeIndexBuffer11(IndexBuffer *indexBuffer); + + virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); + virtual bool unmapBuffer(); + + virtual GLenum getIndexType() const; + virtual unsigned int getBufferSize() const; + virtual bool setSize(unsigned int bufferSize, GLenum indexType); + + virtual bool discard(); + + DXGI_FORMAT getIndexFormat() const; + ID3D11Buffer *getBuffer() const; + + private: + DISALLOW_COPY_AND_ASSIGN(IndexBuffer11); + + rx::Renderer11 *const mRenderer; + + ID3D11Buffer *mBuffer; + unsigned int mBufferSize; + GLenum mIndexType; + bool mDynamicUsage; +}; + +} + +#endif // LIBGLESV2_RENDERER_INDEXBUFFER11_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp new file mode 100644 index 0000000000..4940b8c638 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp @@ -0,0 +1,213 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches +// D3D11 input layouts. + +#include "libGLESv2/renderer/d3d11/InputLayoutCache.h" +#include "libGLESv2/renderer/d3d11/VertexBuffer11.h" +#include "libGLESv2/renderer/d3d11/BufferStorage11.h" +#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h" +#include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/renderer/VertexDataManager.h" + +#include "third_party/murmurhash/MurmurHash3.h" + +namespace rx +{ + +const unsigned int InputLayoutCache::kMaxInputLayouts = 1024; + +InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts) +{ + mCounter = 0; + mDevice = NULL; + mDeviceContext = NULL; + mCurrentIL = NULL; + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mCurrentBuffers[i] = -1; + mCurrentVertexStrides[i] = -1; + mCurrentVertexOffsets[i] = -1; + } +} + +InputLayoutCache::~InputLayoutCache() +{ + clear(); +} + +void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context) +{ + clear(); + mDevice = device; + mDeviceContext = context; +} + +void InputLayoutCache::clear() +{ + for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) + { + i->second.inputLayout->Release(); + } + mInputLayoutMap.clear(); + markDirty(); +} + +void InputLayoutCache::markDirty() +{ + mCurrentIL = NULL; + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mCurrentBuffers[i] = -1; + mCurrentVertexStrides[i] = -1; + mCurrentVertexOffsets[i] = -1; + } +} + +GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], + gl::ProgramBinary *programBinary) +{ + int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]; + programBinary->sortAttributesByLayout(attributes, sortedSemanticIndices); + + if (!mDevice || !mDeviceContext) + { + ERR("InputLayoutCache is not initialized."); + return GL_INVALID_OPERATION; + } + + InputLayoutKey ilKey = { 0 }; + + ID3D11Buffer *vertexBuffers[gl::MAX_VERTEX_ATTRIBS] = { NULL }; + unsigned int vertexBufferSerials[gl::MAX_VERTEX_ATTRIBS] = { 0 }; + UINT vertexStrides[gl::MAX_VERTEX_ATTRIBS] = { 0 }; + UINT vertexOffsets[gl::MAX_VERTEX_ATTRIBS] = { 0 }; + + static const char* semanticName = "TEXCOORD"; + + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (attributes[i].active) + { + VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer); + BufferStorage11 *bufferStorage = attributes[i].storage ? BufferStorage11::makeBufferStorage11(attributes[i].storage) : NULL; + + D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; + + // Record the type of the associated vertex shader vector in our key + // This will prevent mismatched vertex shaders from using the same input layout + GLint attributeSize; + programBinary->getActiveAttribute(sortedSemanticIndices[i], 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL); + + ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName; + ilKey.elements[ilKey.elementCount].desc.SemanticIndex = i; + ilKey.elements[ilKey.elementCount].desc.Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT; + ilKey.elements[ilKey.elementCount].desc.InputSlot = i; + ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; + ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass; + ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = attributes[i].divisor; + ilKey.elementCount++; + + vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX) : vertexBuffer->getBuffer(); + vertexBufferSerials[i] = bufferStorage ? bufferStorage->getSerial() : vertexBuffer->getSerial(); + vertexStrides[i] = attributes[i].stride; + vertexOffsets[i] = attributes[i].offset; + } + } + + ID3D11InputLayout *inputLayout = NULL; + + InputLayoutMap::iterator i = mInputLayoutMap.find(ilKey); + if (i != mInputLayoutMap.end()) + { + inputLayout = i->second.inputLayout; + i->second.lastUsedTime = mCounter++; + } + else + { + ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable()); + + D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS]; + for (unsigned int j = 0; j < ilKey.elementCount; ++j) + { + descs[j] = ilKey.elements[j].desc; + } + + HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout); + if (FAILED(result)) + { + ERR("Failed to crate input layout, result: 0x%08x", result); + return GL_INVALID_OPERATION; + } + + if (mInputLayoutMap.size() >= kMaxInputLayouts) + { + TRACE("Overflowed the limit of %u input layouts, removing the least recently used " + "to make room.", kMaxInputLayouts); + + InputLayoutMap::iterator leastRecentlyUsed = mInputLayoutMap.begin(); + for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) + { + if (i->second.lastUsedTime < leastRecentlyUsed->second.lastUsedTime) + { + leastRecentlyUsed = i; + } + } + leastRecentlyUsed->second.inputLayout->Release(); + mInputLayoutMap.erase(leastRecentlyUsed); + } + + InputLayoutCounterPair inputCounterPair; + inputCounterPair.inputLayout = inputLayout; + inputCounterPair.lastUsedTime = mCounter++; + + mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair)); + } + + if (inputLayout != mCurrentIL) + { + mDeviceContext->IASetInputLayout(inputLayout); + mCurrentIL = inputLayout; + } + + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (vertexBufferSerials[i] != mCurrentBuffers[i] || vertexStrides[i] != mCurrentVertexStrides[i] || + vertexOffsets[i] != mCurrentVertexOffsets[i]) + { + mDeviceContext->IASetVertexBuffers(i, 1, &vertexBuffers[i], &vertexStrides[i], &vertexOffsets[i]); + mCurrentBuffers[i] = vertexBufferSerials[i]; + mCurrentVertexStrides[i] = vertexStrides[i]; + mCurrentVertexOffsets[i] = vertexOffsets[i]; + } + } + + return GL_NO_ERROR; +} + +std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout) +{ + static const unsigned int seed = 0xDEADBEEF; + + std::size_t hash = 0; + MurmurHash3_x86_32(inputLayout.begin(), inputLayout.end() - inputLayout.begin(), seed, &hash); + return hash; +} + +bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b) +{ + if (a.elementCount != b.elementCount) + { + return false; + } + + return std::equal(a.begin(), a.end(), b.begin()); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h new file mode 100644 index 0000000000..bb1a8eebcf --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h @@ -0,0 +1,95 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// InputLayoutCache.h: Defines InputLayoutCache, a class that builds and caches +// D3D11 input layouts. + +#ifndef LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ +#define LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ + +#include "libGLESv2/Constants.h" +#include "common/angleutils.h" + +namespace gl +{ +class ProgramBinary; +} + +namespace rx +{ +struct TranslatedAttribute; + +class InputLayoutCache +{ + public: + InputLayoutCache(); + virtual ~InputLayoutCache(); + + void initialize(ID3D11Device *device, ID3D11DeviceContext *context); + void clear(); + void markDirty(); + + GLenum applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], + gl::ProgramBinary *programBinary); + + private: + DISALLOW_COPY_AND_ASSIGN(InputLayoutCache); + + struct InputLayoutElement + { + D3D11_INPUT_ELEMENT_DESC desc; + GLenum glslElementType; + }; + + struct InputLayoutKey + { + unsigned int elementCount; + InputLayoutElement elements[gl::MAX_VERTEX_ATTRIBS]; + + const char *begin() const + { + return reinterpret_cast(&elementCount); + } + + const char *end() const + { + return reinterpret_cast(&elements[elementCount]); + } + }; + + struct InputLayoutCounterPair + { + ID3D11InputLayout *inputLayout; + unsigned long long lastUsedTime; + }; + + ID3D11InputLayout *mCurrentIL; + unsigned int mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS]; + UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS]; + UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS]; + + static std::size_t hashInputLayout(const InputLayoutKey &inputLayout); + static bool compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b); + + typedef std::size_t (*InputLayoutHashFunction)(const InputLayoutKey &); + typedef bool (*InputLayoutEqualityFunction)(const InputLayoutKey &, const InputLayoutKey &); + typedef std::unordered_map InputLayoutMap; + InputLayoutMap mInputLayoutMap; + + static const unsigned int kMaxInputLayouts; + + unsigned long long mCounter; + + ID3D11Device *mDevice; + ID3D11DeviceContext *mDeviceContext; +}; + +} + +#endif // LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp new file mode 100644 index 0000000000..24c0330a1e --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp @@ -0,0 +1,122 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl. + +#include "libGLESv2/renderer/d3d11/Query11.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +Query11::Query11(rx::Renderer11 *renderer, GLenum type) : QueryImpl(type) +{ + mRenderer = renderer; + mQuery = NULL; +} + +Query11::~Query11() +{ + if (mQuery) + { + mQuery->Release(); + mQuery = NULL; + } +} + +void Query11::begin() +{ + if (mQuery == NULL) + { + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = D3D11_QUERY_OCCLUSION; + queryDesc.MiscFlags = 0; + + if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery))) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + mRenderer->getDeviceContext()->Begin(mQuery); +} + +void Query11::end() +{ + if (mQuery == NULL) + { + return gl::error(GL_INVALID_OPERATION); + } + + mRenderer->getDeviceContext()->End(mQuery); + + mStatus = GL_FALSE; + mResult = GL_FALSE; +} + +GLuint Query11::getResult() +{ + if (mQuery != NULL) + { + while (!testQuery()) + { + Sleep(0); + // explicitly check for device loss, some drivers seem to return S_FALSE + // if the device is lost + if (mRenderer->testDeviceLost(true)) + { + return gl::error(GL_OUT_OF_MEMORY, 0); + } + } + } + + return mResult; +} + +GLboolean Query11::isResultAvailable() +{ + if (mQuery != NULL) + { + testQuery(); + } + + return mStatus; +} + +GLboolean Query11::testQuery() +{ + if (mQuery != NULL && mStatus != GL_TRUE) + { + UINT64 numPixels = 0; + HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, &numPixels, sizeof(UINT64), 0); + if (result == S_OK) + { + mStatus = GL_TRUE; + + switch (getType()) + { + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: + mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; + break; + default: + UNREACHABLE(); + } + } + else if (mRenderer->testDeviceLost(true)) + { + return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); + } + + return mStatus; + } + + return GL_TRUE; // prevent blocking when query is null +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.h new file mode 100644 index 0000000000..0a03de77ca --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Query11.h: Defines the rx::Query11 class which implements rx::QueryImpl. + +#ifndef LIBGLESV2_RENDERER_QUERY11_H_ +#define LIBGLESV2_RENDERER_QUERY11_H_ + +#include "libGLESv2/renderer/QueryImpl.h" + +namespace rx +{ +class Renderer11; + +class Query11 : public QueryImpl +{ + public: + Query11(rx::Renderer11 *renderer, GLenum type); + virtual ~Query11(); + + void begin(); + void end(); + GLuint getResult(); + GLboolean isResultAvailable(); + + private: + DISALLOW_COPY_AND_ASSIGN(Query11); + + GLboolean testQuery(); + + rx::Renderer11 *mRenderer; + ID3D11Query *mQuery; +}; + +} + +#endif // LIBGLESV2_RENDERER_QUERY11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp new file mode 100644 index 0000000000..a1c324cd80 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp @@ -0,0 +1,439 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render +// state objects. + +#include "libGLESv2/renderer/d3d11/RenderStateCache.h" +#include "libGLESv2/renderer/d3d11/renderer11_utils.h" + +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/utilities.h" +#include "common/debug.h" +#include "third_party/murmurhash/MurmurHash3.h" + +namespace rx +{ + +// MSDN's documentation of ID3D11Device::CreateBlendState, ID3D11Device::CreateRasterizerState, +// ID3D11Device::CreateDepthStencilState and ID3D11Device::CreateSamplerState claims the maximum +// number of unique states of each type an application can create is 4096 +const unsigned int RenderStateCache::kMaxBlendStates = 4096; +const unsigned int RenderStateCache::kMaxRasterizerStates = 4096; +const unsigned int RenderStateCache::kMaxDepthStencilStates = 4096; +const unsigned int RenderStateCache::kMaxSamplerStates = 4096; + +RenderStateCache::RenderStateCache() : mDevice(NULL), mCounter(0), + mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates), + mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates), + mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates), + mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates) +{ +} + +RenderStateCache::~RenderStateCache() +{ + clear(); +} + +void RenderStateCache::initialize(ID3D11Device *device) +{ + clear(); + mDevice = device; +} + +void RenderStateCache::clear() +{ + for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++) + { + i->second.first->Release(); + } + mBlendStateCache.clear(); + + for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++) + { + i->second.first->Release(); + } + mRasterizerStateCache.clear(); + + for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++) + { + i->second.first->Release(); + } + mDepthStencilStateCache.clear(); + + for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++) + { + i->second.first->Release(); + } + mSamplerStateCache.clear(); +} + +std::size_t RenderStateCache::hashBlendState(const BlendStateKey &blendState) +{ + static const unsigned int seed = 0xABCDEF98; + + std::size_t hash = 0; + MurmurHash3_x86_32(&blendState, sizeof(BlendStateKey), seed, &hash); + return hash; +} + +bool RenderStateCache::compareBlendStates(const BlendStateKey &a, const BlendStateKey &b) +{ + return memcmp(&a, &b, sizeof(gl::BlendState)) == 0; +} + +ID3D11BlendState *RenderStateCache::getBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState) +{ + if (!mDevice) + { + ERR("RenderStateCache is not initialized."); + return NULL; + } + + bool mrt = false; + + BlendStateKey key = { 0 }; + key.blendState = blendState; + for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + { + gl::Renderbuffer *renderBuffer = framebuffer->getColorbuffer(i); + if (renderBuffer) + { + if (i > 0) + { + mrt = true; + } + + GLenum internalFormat = renderBuffer->getInternalFormat(); + key.rtChannels[i][0] = gl::GetRedSize(internalFormat) > 0; + key.rtChannels[i][1] = gl::GetGreenSize(internalFormat) > 0; + key.rtChannels[i][2] = gl::GetBlueSize(internalFormat) > 0;; + key.rtChannels[i][3] = gl::GetAlphaSize(internalFormat) > 0; + } + else + { + key.rtChannels[i][0] = false; + key.rtChannels[i][1] = false; + key.rtChannels[i][2] = false; + key.rtChannels[i][3] = false; + } + } + + BlendStateMap::iterator i = mBlendStateCache.find(key); + if (i != mBlendStateCache.end()) + { + BlendStateCounterPair &state = i->second; + state.second = mCounter++; + return state.first; + } + else + { + if (mBlendStateCache.size() >= kMaxBlendStates) + { + TRACE("Overflowed the limit of %u blend states, removing the least recently used " + "to make room.", kMaxBlendStates); + + BlendStateMap::iterator leastRecentlyUsed = mBlendStateCache.begin(); + for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) + { + leastRecentlyUsed = i; + } + } + leastRecentlyUsed->second.first->Release(); + mBlendStateCache.erase(leastRecentlyUsed); + } + + // Create a new blend state and insert it into the cache + D3D11_BLEND_DESC blendDesc = { 0 }; + blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage; + blendDesc.IndependentBlendEnable = mrt ? TRUE : FALSE; + + for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + { + D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = blendDesc.RenderTarget[i]; + + rtBlend.BlendEnable = blendState.blend; + if (blendState.blend) + { + rtBlend.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false); + rtBlend.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false); + rtBlend.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB); + + rtBlend.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true); + rtBlend.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true); + rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha); + } + + rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(key.rtChannels[i][0] && blendState.colorMaskRed, + key.rtChannels[i][1] && blendState.colorMaskGreen, + key.rtChannels[i][2] && blendState.colorMaskBlue, + key.rtChannels[i][3] && blendState.colorMaskAlpha); + } + + ID3D11BlendState *dx11BlendState = NULL; + HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState); + if (FAILED(result) || !dx11BlendState) + { + ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); + return NULL; + } + + mBlendStateCache.insert(std::make_pair(key, std::make_pair(dx11BlendState, mCounter++))); + + return dx11BlendState; + } +} + +std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rasterState) +{ + static const unsigned int seed = 0xABCDEF98; + + std::size_t hash = 0; + MurmurHash3_x86_32(&rasterState, sizeof(RasterizerStateKey), seed, &hash); + return hash; +} + +bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b) +{ + return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0; +} + +ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, + bool scissorEnabled, unsigned int depthSize) +{ + if (!mDevice) + { + ERR("RenderStateCache is not initialized."); + return NULL; + } + + RasterizerStateKey key; + key.rasterizerState = rasterState; + key.scissorEnabled = scissorEnabled; + key.depthSize = depthSize; + + RasterizerStateMap::iterator i = mRasterizerStateCache.find(key); + if (i != mRasterizerStateCache.end()) + { + RasterizerStateCounterPair &state = i->second; + state.second = mCounter++; + return state.first; + } + else + { + if (mRasterizerStateCache.size() >= kMaxRasterizerStates) + { + TRACE("Overflowed the limit of %u rasterizer states, removing the least recently used " + "to make room.", kMaxRasterizerStates); + + RasterizerStateMap::iterator leastRecentlyUsed = mRasterizerStateCache.begin(); + for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) + { + leastRecentlyUsed = i; + } + } + leastRecentlyUsed->second.first->Release(); + mRasterizerStateCache.erase(leastRecentlyUsed); + } + + D3D11_CULL_MODE cullMode = gl_d3d11::ConvertCullMode(rasterState.cullFace, rasterState.cullMode); + + // Disable culling if drawing points + if (rasterState.pointDrawMode) + { + cullMode = D3D11_CULL_NONE; + } + + D3D11_RASTERIZER_DESC rasterDesc; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.CullMode = cullMode; + rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? FALSE: TRUE; + rasterDesc.DepthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast(depthSize)); + rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though. + rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor; + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE; + rasterDesc.MultisampleEnable = rasterState.multiSample; + rasterDesc.AntialiasedLineEnable = FALSE; + + ID3D11RasterizerState *dx11RasterizerState = NULL; + HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState); + if (FAILED(result) || !dx11RasterizerState) + { + ERR("Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result); + return NULL; + } + + mRasterizerStateCache.insert(std::make_pair(key, std::make_pair(dx11RasterizerState, mCounter++))); + + return dx11RasterizerState; + } +} + +std::size_t RenderStateCache::hashDepthStencilState(const gl::DepthStencilState &dsState) +{ + static const unsigned int seed = 0xABCDEF98; + + std::size_t hash = 0; + MurmurHash3_x86_32(&dsState, sizeof(gl::DepthStencilState), seed, &hash); + return hash; +} + +bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b) +{ + return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0; +} + +ID3D11DepthStencilState *RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState) +{ + if (!mDevice) + { + ERR("RenderStateCache is not initialized."); + return NULL; + } + + DepthStencilStateMap::iterator i = mDepthStencilStateCache.find(dsState); + if (i != mDepthStencilStateCache.end()) + { + DepthStencilStateCounterPair &state = i->second; + state.second = mCounter++; + return state.first; + } + else + { + if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates) + { + TRACE("Overflowed the limit of %u depth stencil states, removing the least recently used " + "to make room.", kMaxDepthStencilStates); + + DepthStencilStateMap::iterator leastRecentlyUsed = mDepthStencilStateCache.begin(); + for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) + { + leastRecentlyUsed = i; + } + } + leastRecentlyUsed->second.first->Release(); + mDepthStencilStateCache.erase(leastRecentlyUsed); + } + + D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 }; + dsDesc.DepthEnable = dsState.depthTest ? TRUE : FALSE; + dsDesc.DepthWriteMask = gl_d3d11::ConvertDepthMask(dsState.depthMask); + dsDesc.DepthFunc = gl_d3d11::ConvertComparison(dsState.depthFunc); + dsDesc.StencilEnable = dsState.stencilTest ? TRUE : FALSE; + dsDesc.StencilReadMask = gl_d3d11::ConvertStencilMask(dsState.stencilMask); + dsDesc.StencilWriteMask = gl_d3d11::ConvertStencilMask(dsState.stencilWritemask); + dsDesc.FrontFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilFail); + dsDesc.FrontFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthFail); + dsDesc.FrontFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthPass); + dsDesc.FrontFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilFunc); + dsDesc.BackFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackFail); + dsDesc.BackFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthFail); + dsDesc.BackFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthPass); + dsDesc.BackFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilBackFunc); + + ID3D11DepthStencilState *dx11DepthStencilState = NULL; + HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState); + if (FAILED(result) || !dx11DepthStencilState) + { + ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); + return NULL; + } + + mDepthStencilStateCache.insert(std::make_pair(dsState, std::make_pair(dx11DepthStencilState, mCounter++))); + + return dx11DepthStencilState; + } +} + +std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState) +{ + static const unsigned int seed = 0xABCDEF98; + + std::size_t hash = 0; + MurmurHash3_x86_32(&samplerState, sizeof(gl::SamplerState), seed, &hash); + return hash; +} + +bool RenderStateCache::compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b) +{ + return memcmp(&a, &b, sizeof(gl::SamplerState)) == 0; +} + +ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &samplerState) +{ + if (!mDevice) + { + ERR("RenderStateCache is not initialized."); + return NULL; + } + + SamplerStateMap::iterator i = mSamplerStateCache.find(samplerState); + if (i != mSamplerStateCache.end()) + { + SamplerStateCounterPair &state = i->second; + state.second = mCounter++; + return state.first; + } + else + { + if (mSamplerStateCache.size() >= kMaxSamplerStates) + { + TRACE("Overflowed the limit of %u sampler states, removing the least recently used " + "to make room.", kMaxSamplerStates); + + SamplerStateMap::iterator leastRecentlyUsed = mSamplerStateCache.begin(); + for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) + { + leastRecentlyUsed = i; + } + } + leastRecentlyUsed->second.first->Release(); + mSamplerStateCache.erase(leastRecentlyUsed); + } + + D3D11_SAMPLER_DESC samplerDesc; + samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter, samplerState.maxAnisotropy); + samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS); + samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT); + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.MipLODBias = static_cast(samplerState.lodOffset); + samplerDesc.MaxAnisotropy = samplerState.maxAnisotropy; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + samplerDesc.BorderColor[0] = 0.0f; + samplerDesc.BorderColor[1] = 0.0f; + samplerDesc.BorderColor[2] = 0.0f; + samplerDesc.BorderColor[3] = 0.0f; + samplerDesc.MinLOD = gl_d3d11::ConvertMinLOD(samplerState.minFilter, samplerState.lodOffset); + samplerDesc.MaxLOD = mDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_0 + ? gl_d3d11::ConvertMaxLOD(samplerState.minFilter, samplerState.lodOffset) : FLT_MAX; + + ID3D11SamplerState *dx11SamplerState = NULL; + HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState); + if (FAILED(result) || !dx11SamplerState) + { + ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); + return NULL; + } + + mSamplerStateCache.insert(std::make_pair(samplerState, std::make_pair(dx11SamplerState, mCounter++))); + + return dx11SamplerState; + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h new file mode 100644 index 0000000000..b4b871a4bd --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h @@ -0,0 +1,111 @@ +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderStateCache.h: Defines rx::RenderStateCache, a cache of Direct3D render +// state objects. + +#ifndef LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ +#define LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ + +#include "libGLESv2/angletypes.h" +#include "common/angleutils.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ + +class RenderStateCache +{ + public: + RenderStateCache(); + virtual ~RenderStateCache(); + + void initialize(ID3D11Device *device); + void clear(); + + // Increments refcount on the returned blend state, Release() must be called. + ID3D11BlendState *getBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState); + ID3D11RasterizerState *getRasterizerState(const gl::RasterizerState &rasterState, + bool scissorEnabled, unsigned int depthSize); + ID3D11DepthStencilState *getDepthStencilState(const gl::DepthStencilState &dsState); + ID3D11SamplerState *getSamplerState(const gl::SamplerState &samplerState); + + private: + DISALLOW_COPY_AND_ASSIGN(RenderStateCache); + + unsigned long long mCounter; + + // Blend state cache + struct BlendStateKey + { + gl::BlendState blendState; + bool rtChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4]; + }; + static std::size_t hashBlendState(const BlendStateKey &blendState); + static bool compareBlendStates(const BlendStateKey &a, const BlendStateKey &b); + static const unsigned int kMaxBlendStates; + + typedef std::size_t (*BlendStateHashFunction)(const BlendStateKey &); + typedef bool (*BlendStateEqualityFunction)(const BlendStateKey &, const BlendStateKey &); + typedef std::pair BlendStateCounterPair; + typedef std::unordered_map BlendStateMap; + BlendStateMap mBlendStateCache; + + // Rasterizer state cache + struct RasterizerStateKey + { + gl::RasterizerState rasterizerState; + bool scissorEnabled; + unsigned int depthSize; + }; + static std::size_t hashRasterizerState(const RasterizerStateKey &rasterState); + static bool compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b); + static const unsigned int kMaxRasterizerStates; + + typedef std::size_t (*RasterizerStateHashFunction)(const RasterizerStateKey &); + typedef bool (*RasterizerStateEqualityFunction)(const RasterizerStateKey &, const RasterizerStateKey &); + typedef std::pair RasterizerStateCounterPair; + typedef std::unordered_map RasterizerStateMap; + RasterizerStateMap mRasterizerStateCache; + + // Depth stencil state cache + static std::size_t hashDepthStencilState(const gl::DepthStencilState &dsState); + static bool compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b); + static const unsigned int kMaxDepthStencilStates; + + typedef std::size_t (*DepthStencilStateHashFunction)(const gl::DepthStencilState &); + typedef bool (*DepthStencilStateEqualityFunction)(const gl::DepthStencilState &, const gl::DepthStencilState &); + typedef std::pair DepthStencilStateCounterPair; + typedef std::unordered_map DepthStencilStateMap; + DepthStencilStateMap mDepthStencilStateCache; + + // Sample state cache + static std::size_t hashSamplerState(const gl::SamplerState &samplerState); + static bool compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b); + static const unsigned int kMaxSamplerStates; + + typedef std::size_t (*SamplerStateHashFunction)(const gl::SamplerState &); + typedef bool (*SamplerStateEqualityFunction)(const gl::SamplerState &, const gl::SamplerState &); + typedef std::pair SamplerStateCounterPair; + typedef std::unordered_map SamplerStateMap; + SamplerStateMap mSamplerStateCache; + + ID3D11Device *mDevice; +}; + +} + +#endif // LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp new file mode 100644 index 0000000000..3707097aa4 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp @@ -0,0 +1,355 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers +// retained by Renderbuffers. + +#include "libGLESv2/renderer/d3d11/RenderTarget11.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" + +#include "libGLESv2/renderer/d3d11/renderer11_utils.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +static unsigned int getRTVSubresourceIndex(ID3D11Texture2D *texture, ID3D11RenderTargetView *view) +{ + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + view->GetDesc(&rtvDesc); + + D3D11_TEXTURE2D_DESC texDesc; + texture->GetDesc(&texDesc); + + unsigned int mipSlice = 0; + unsigned int arraySlice = 0; + unsigned int mipLevels = texDesc.MipLevels; + + switch (rtvDesc.ViewDimension) + { + case D3D11_RTV_DIMENSION_TEXTURE1D: + mipSlice = rtvDesc.Texture1D.MipSlice; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: + mipSlice = rtvDesc.Texture1DArray.MipSlice; + arraySlice = rtvDesc.Texture1DArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2D: + mipSlice = rtvDesc.Texture2D.MipSlice; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: + mipSlice = rtvDesc.Texture2DArray.MipSlice; + arraySlice = rtvDesc.Texture2DArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DMS: + mipSlice = 0; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: + mipSlice = 0; + arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE3D: + mipSlice = rtvDesc.Texture3D.MipSlice; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_UNKNOWN: + case D3D11_RTV_DIMENSION_BUFFER: + UNIMPLEMENTED(); + break; + + default: + UNREACHABLE(); + break; + } + + return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); +} + +static unsigned int getDSVSubresourceIndex(ID3D11Texture2D *texture, ID3D11DepthStencilView *view) +{ + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + view->GetDesc(&dsvDesc); + + D3D11_TEXTURE2D_DESC texDesc; + texture->GetDesc(&texDesc); + + unsigned int mipSlice = 0; + unsigned int arraySlice = 0; + unsigned int mipLevels = texDesc.MipLevels; + + switch (dsvDesc.ViewDimension) + { + case D3D11_DSV_DIMENSION_TEXTURE1D: + mipSlice = dsvDesc.Texture1D.MipSlice; + arraySlice = 0; + break; + + case D3D11_DSV_DIMENSION_TEXTURE1DARRAY: + mipSlice = dsvDesc.Texture1DArray.MipSlice; + arraySlice = dsvDesc.Texture1DArray.FirstArraySlice; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2D: + mipSlice = dsvDesc.Texture2D.MipSlice; + arraySlice = 0; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: + mipSlice = dsvDesc.Texture2DArray.MipSlice; + arraySlice = dsvDesc.Texture2DArray.FirstArraySlice; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMS: + mipSlice = 0; + arraySlice = 0; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: + mipSlice = 0; + arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_UNKNOWN: + UNIMPLEMENTED(); + break; + + default: + UNREACHABLE(); + break; + } + + return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); +} + +RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height) +{ + mRenderer = Renderer11::makeRenderer11(renderer); + mTexture = tex; + mRenderTarget = rtv; + mDepthStencil = NULL; + mShaderResource = srv; + mSubresourceIndex = 0; + + if (mRenderTarget && mTexture) + { + D3D11_RENDER_TARGET_VIEW_DESC desc; + mRenderTarget->GetDesc(&desc); + + D3D11_TEXTURE2D_DESC texDesc; + mTexture->GetDesc(&texDesc); + + mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget); + mWidth = width; + mHeight = height; + mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0; + + mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); + mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); + } +} + +RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height) +{ + mRenderer = Renderer11::makeRenderer11(renderer); + mTexture = tex; + mRenderTarget = NULL; + mDepthStencil = dsv; + mShaderResource = srv; + mSubresourceIndex = 0; + + if (mDepthStencil && mTexture) + { + D3D11_DEPTH_STENCIL_VIEW_DESC desc; + mDepthStencil->GetDesc(&desc); + + D3D11_TEXTURE2D_DESC texDesc; + mTexture->GetDesc(&texDesc); + + mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil); + mWidth = width; + mHeight = height; + mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0; + + mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); + mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); + } +} + +RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth) +{ + mRenderer = Renderer11::makeRenderer11(renderer); + mTexture = NULL; + mRenderTarget = NULL; + mDepthStencil = NULL; + mShaderResource = NULL; + + DXGI_FORMAT requestedFormat = gl_d3d11::ConvertRenderbufferFormat(format); + + int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples); + if (supportedSamples < 0) + { + gl::error(GL_OUT_OF_MEMORY); + return; + } + + if (width > 0 && height > 0) + { + // Create texture resource + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = requestedFormat; + desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + desc.BindFlags = (depth ? D3D11_BIND_DEPTH_STENCIL : (D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)); + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + + if (result == E_OUTOFMEMORY) + { + gl::error(GL_OUT_OF_MEMORY); + return; + } + ASSERT(SUCCEEDED(result)); + + if (depth) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = requestedFormat; + dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; + dsvDesc.Texture2D.MipSlice = 0; + dsvDesc.Flags = 0; + result = device->CreateDepthStencilView(mTexture, &dsvDesc, &mDepthStencil); + + if (result == E_OUTOFMEMORY) + { + mTexture->Release(); + mTexture = NULL; + gl::error(GL_OUT_OF_MEMORY); + } + ASSERT(SUCCEEDED(result)); + } + else + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = requestedFormat; + rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; + rtvDesc.Texture2D.MipSlice = 0; + result = device->CreateRenderTargetView(mTexture, &rtvDesc, &mRenderTarget); + + if (result == E_OUTOFMEMORY) + { + mTexture->Release(); + mTexture = NULL; + gl::error(GL_OUT_OF_MEMORY); + return; + } + ASSERT(SUCCEEDED(result)); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = requestedFormat; + srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.MipLevels = 1; + result = device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResource); + + if (result == E_OUTOFMEMORY) + { + mTexture->Release(); + mTexture = NULL; + mRenderTarget->Release(); + mRenderTarget = NULL; + gl::error(GL_OUT_OF_MEMORY); + return; + } + ASSERT(SUCCEEDED(result)); + } + } + + mWidth = width; + mHeight = height; + mInternalFormat = format; + mSamples = supportedSamples; + mActualFormat = d3d11_gl::ConvertTextureInternalFormat(requestedFormat); + mSubresourceIndex = D3D11CalcSubresource(0, 0, 1); +} + +RenderTarget11::~RenderTarget11() +{ + if (mTexture) + { + mTexture->Release(); + mTexture = NULL; + } + + if (mRenderTarget) + { + mRenderTarget->Release(); + mRenderTarget = NULL; + } + + if (mDepthStencil) + { + mDepthStencil->Release(); + mDepthStencil = NULL; + } + + if (mShaderResource) + { + mShaderResource->Release(); + mShaderResource = NULL; + } +} + +RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget11*, target)); + return static_cast(target); +} + +ID3D11Texture2D *RenderTarget11::getTexture() const +{ + return mTexture; +} + +ID3D11RenderTargetView *RenderTarget11::getRenderTargetView() const +{ + return mRenderTarget; +} + +ID3D11DepthStencilView *RenderTarget11::getDepthStencilView() const +{ + return mDepthStencil; +} + +ID3D11ShaderResourceView *RenderTarget11::getShaderResourceView() const +{ + return mShaderResource; +} + +unsigned int RenderTarget11::getSubresourceIndex() const +{ + return mSubresourceIndex; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.h new file mode 100644 index 0000000000..97827f2639 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.h @@ -0,0 +1,51 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderTarget11.h: Defines a DX11-specific wrapper for ID3D11View pointers +// retained by Renderbuffers. + +#ifndef LIBGLESV2_RENDERER_RENDERTARGET11_H_ +#define LIBGLESV2_RENDERER_RENDERTARGET11_H_ + +#include "libGLESv2/renderer/RenderTarget.h" + +namespace rx +{ +class Renderer; +class Renderer11; + +class RenderTarget11 : public RenderTarget +{ + public: + RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height); + RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height); + RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth); + virtual ~RenderTarget11(); + + static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget); + + ID3D11Texture2D *getTexture() const; + ID3D11RenderTargetView *getRenderTargetView() const; + ID3D11DepthStencilView *getDepthStencilView() const; + ID3D11ShaderResourceView *getShaderResourceView() const; + + unsigned int getSubresourceIndex() const; + + private: + DISALLOW_COPY_AND_ASSIGN(RenderTarget11); + + unsigned int mSubresourceIndex; + ID3D11Texture2D *mTexture; + ID3D11RenderTargetView *mRenderTarget; + ID3D11DepthStencilView *mDepthStencil; + ID3D11ShaderResourceView *mShaderResource; + + Renderer11 *mRenderer; +}; + +} + +#endif LIBGLESV2_RENDERER_RENDERTARGET11_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp new file mode 100644 index 0000000000..31d976dec4 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp @@ -0,0 +1,3670 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer. + +#include "libGLESv2/main.h" +#include "libGLESv2/utilities.h" +#include "libGLESv2/Buffer.h" +#include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d11/RenderTarget11.h" +#include "libGLESv2/renderer/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h" +#include "libGLESv2/renderer/d3d11/SwapChain11.h" +#include "libGLESv2/renderer/d3d11/Image11.h" +#include "libGLESv2/renderer/d3d11/VertexBuffer11.h" +#include "libGLESv2/renderer/d3d11/IndexBuffer11.h" +#include "libGLESv2/renderer/d3d11/BufferStorage11.h" +#include "libGLESv2/renderer/VertexDataManager.h" +#include "libGLESv2/renderer/IndexDataManager.h" +#include "libGLESv2/renderer/d3d11/TextureStorage11.h" +#include "libGLESv2/renderer/d3d11/Query11.h" +#include "libGLESv2/renderer/d3d11/Fence11.h" + +#include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h" +#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h" +#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb11ps.h" +#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum11ps.h" +#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha11ps.h" + +#include "libGLESv2/renderer/d3d11/shaders/compiled/clear11vs.h" +#include "libGLESv2/renderer/d3d11/shaders/compiled/clearsingle11ps.h" +#include "libGLESv2/renderer/d3d11/shaders/compiled/clearmultiple11ps.h" + +#include "libEGL/Display.h" + +#ifdef _DEBUG +// this flag enables suppressing some spurious warnings that pop up in certain WebGL samples +// and conformance tests. to enable all warnings, remove this define. +#define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1 +#endif + +namespace rx +{ +static const DXGI_FORMAT RenderTargetFormats[] = + { + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM + }; + +static const DXGI_FORMAT DepthStencilFormats[] = + { + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_D16_UNORM + }; + +enum +{ + MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 +}; + +Renderer11::Renderer11(egl::Display *display) : Renderer(display) +{ + mVertexDataManager = NULL; + mIndexDataManager = NULL; + + mLineLoopIB = NULL; + mTriangleFanIB = NULL; + + mCopyResourcesInitialized = false; + mCopyVB = NULL; + mCopySampler = NULL; + mCopyIL = NULL; + mCopyVS = NULL; + mCopyRGBAPS = NULL; + mCopyRGBPS = NULL; + mCopyLumPS = NULL; + mCopyLumAlphaPS = NULL; + + mClearResourcesInitialized = false; + mClearVB = NULL; + mClearIL = NULL; + mClearVS = NULL; + mClearSinglePS = NULL; + mClearMultiplePS = NULL; + mClearScissorRS = NULL; + mClearNoScissorRS = NULL; + + mSyncQuery = NULL; + + mD3d11Module = NULL; + mDxgiModule = NULL; + + mDeviceLost = false; + + mMaxSupportedSamples = 0; + + mDevice = NULL; + mDeviceContext = NULL; + mDxgiAdapter = NULL; + mDxgiFactory = NULL; + + mDriverConstantBufferVS = NULL; + mDriverConstantBufferPS = NULL; + + mBGRATextureSupport = false; + + mIsGeometryShaderActive = false; +} + +Renderer11::~Renderer11() +{ + release(); +} + +Renderer11 *Renderer11::makeRenderer11(Renderer *renderer) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer11*, renderer)); + return static_cast(renderer); +} + +#ifndef __d3d11_1_h__ +#define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081) +#endif + +EGLint Renderer11::initialize() +{ + if (!initializeCompiler()) + { + return EGL_NOT_INITIALIZED; + } + +#if !defined(ANGLE_OS_WINRT) + mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); + mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); + + if (mD3d11Module == NULL || mDxgiModule == NULL) + { + ERR("Could not load D3D11 or DXGI library - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + + // create the D3D11 device + ASSERT(mDevice == NULL); + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); + + if (D3D11CreateDevice == NULL) + { + ERR("Could not retrieve D3D11CreateDevice address - aborting!\n"); + return EGL_NOT_INITIALIZED; + } +#endif + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, +#if !defined(ANGLE_ENABLE_D3D9) + D3D_FEATURE_LEVEL_9_3, + D3D_FEATURE_LEVEL_9_2, + D3D_FEATURE_LEVEL_9_1, +#endif + }; + + HRESULT result = S_OK; + +#ifdef _DEBUG + result = D3D11CreateDevice(NULL, + D3D_DRIVER_TYPE_HARDWARE, + NULL, + D3D11_CREATE_DEVICE_DEBUG, + featureLevels, + ArraySize(featureLevels), + D3D11_SDK_VERSION, + &mDevice, + &mFeatureLevel, + &mDeviceContext); + + if (!mDevice || FAILED(result)) + { + ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n"); + } + + if (!mDevice || FAILED(result)) +#endif + { + result = D3D11CreateDevice(NULL, + D3D_DRIVER_TYPE_HARDWARE, + NULL, + 0, + featureLevels, + ArraySize(featureLevels), + D3D11_SDK_VERSION, + &mDevice, + &mFeatureLevel, + &mDeviceContext); + + if (!mDevice || FAILED(result)) + { + ERR("Could not create D3D11 device - aborting!\n"); + return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer + } + } + +#if !defined(ANGLE_OS_WINRT) + IDXGIDevice *dxgiDevice = NULL; +#else + IDXGIDevice1 *dxgiDevice = NULL; +#endif + result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice)); + + if (FAILED(result)) + { + ERR("Could not query DXGI device - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter); + + if (FAILED(result)) + { + ERR("Could not retrieve DXGI adapter - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + dxgiDevice->Release(); + + mDxgiAdapter->GetDesc(&mAdapterDescription); + memset(mDescription, 0, sizeof(mDescription)); + wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1); + + result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory); + + if (!mDxgiFactory || FAILED(result)) + { + ERR("Could not create DXGI factory - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log +#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) + ID3D11InfoQueue *infoQueue; + result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue); + + if (SUCCEEDED(result)) + { + D3D11_MESSAGE_ID hideMessages[] = + { + D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET + }; + + D3D11_INFO_QUEUE_FILTER filter = {0}; + filter.DenyList.NumIDs = ArraySize(hideMessages); + filter.DenyList.pIDList = hideMessages; + + infoQueue->AddStorageFilterEntries(&filter); + + infoQueue->Release(); + } +#endif + + unsigned int maxSupportedSamples = 0; + unsigned int rtFormatCount = ArraySize(RenderTargetFormats); + unsigned int dsFormatCount = ArraySize(DepthStencilFormats); + for (unsigned int i = 0; i < rtFormatCount + dsFormatCount; ++i) + { + DXGI_FORMAT format = (i < rtFormatCount) ? RenderTargetFormats[i] : DepthStencilFormats[i - rtFormatCount]; + if (format != DXGI_FORMAT_UNKNOWN) + { + UINT formatSupport; + result = mDevice->CheckFormatSupport(format, &formatSupport); + if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET)) + { + MultisampleSupportInfo supportInfo; + + for (unsigned int j = 1; j <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; j++) + { + result = mDevice->CheckMultisampleQualityLevels(format, j, &supportInfo.qualityLevels[j - 1]); + if (SUCCEEDED(result) && supportInfo.qualityLevels[j - 1] > 0) + { + maxSupportedSamples = std::max(j, maxSupportedSamples); + } + else + { + supportInfo.qualityLevels[j - 1] = 0; + } + } + + mMultisampleSupportMap.insert(std::make_pair(format, supportInfo)); + } + } + } + mMaxSupportedSamples = maxSupportedSamples; + + initializeDevice(); + + // BGRA texture support is optional in feature levels 10 and 10_1 + UINT formatSupport; + result = mDevice->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &formatSupport); + if (FAILED(result)) + { + ERR("Error checking BGRA format support: 0x%08X", result); + } + else + { + const int flags = (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET); + mBGRATextureSupport = (formatSupport & flags) == flags; + } + + // Check floating point texture support + static const unsigned int requiredTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE; + static const unsigned int requiredRenderableFlags = D3D11_FORMAT_SUPPORT_RENDER_TARGET; + static const unsigned int requiredFilterFlags = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE; + + DXGI_FORMAT float16Formats[] = + { + DXGI_FORMAT_R16_FLOAT, + DXGI_FORMAT_R16G16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + }; + + DXGI_FORMAT float32Formats[] = + { + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + }; + + mFloat16TextureSupport = true; + mFloat16FilterSupport = true; + mFloat16RenderSupport = true; + for (unsigned int i = 0; i < ArraySize(float16Formats); i++) + { + if (SUCCEEDED(mDevice->CheckFormatSupport(float16Formats[i], &formatSupport))) + { + mFloat16TextureSupport = mFloat16TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags; + mFloat16FilterSupport = mFloat16FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags; + mFloat16RenderSupport = mFloat16RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags; + } + else + { + mFloat16TextureSupport = false; + mFloat16RenderSupport = false; + mFloat16FilterSupport = false; + } + } + + mFloat32TextureSupport = true; + mFloat32FilterSupport = true; + mFloat32RenderSupport = true; + for (unsigned int i = 0; i < ArraySize(float32Formats); i++) + { + if (SUCCEEDED(mDevice->CheckFormatSupport(float32Formats[i], &formatSupport))) + { + mFloat32TextureSupport = mFloat32TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags; + mFloat32FilterSupport = mFloat32FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags; + mFloat32RenderSupport = mFloat32RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags; + } + else + { + mFloat32TextureSupport = false; + mFloat32FilterSupport = false; + mFloat32RenderSupport = false; + } + } + + // Check compressed texture support + const unsigned int requiredCompressedTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D; + + if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC1_UNORM, &formatSupport))) + { + mDXT1TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; + } + else + { + mDXT1TextureSupport = false; + } + + if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC3_UNORM, &formatSupport))) + { + mDXT3TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; + } + else + { + mDXT3TextureSupport = false; + } + + if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC5_UNORM, &formatSupport))) + { + mDXT5TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; + } + else + { + mDXT5TextureSupport = false; + } + + // Check depth texture support + DXGI_FORMAT depthTextureFormats[] = + { + DXGI_FORMAT_D16_UNORM, + DXGI_FORMAT_D24_UNORM_S8_UINT, + }; + + static const unsigned int requiredDepthTextureFlags = D3D11_FORMAT_SUPPORT_DEPTH_STENCIL | + D3D11_FORMAT_SUPPORT_TEXTURE2D; + + mDepthTextureSupport = true; + for (unsigned int i = 0; i < ArraySize(depthTextureFormats); i++) + { + if (SUCCEEDED(mDevice->CheckFormatSupport(depthTextureFormats[i], &formatSupport))) + { + mDepthTextureSupport = mDepthTextureSupport && ((formatSupport & requiredDepthTextureFlags) == requiredDepthTextureFlags); + } + else + { + mDepthTextureSupport = false; + } + } + + return EGL_SUCCESS; +} + +// do any one-time device initialization +// NOTE: this is also needed after a device lost/reset +// to reset the scene status and ensure the default states are reset. +void Renderer11::initializeDevice() +{ + mStateCache.initialize(mDevice); + mInputLayoutCache.initialize(mDevice, mDeviceContext); + + ASSERT(!mVertexDataManager && !mIndexDataManager); + mVertexDataManager = new VertexDataManager(this); + mIndexDataManager = new IndexDataManager(this); + + markAllStateDirty(); +} + +int Renderer11::generateConfigs(ConfigDesc **configDescList) +{ + unsigned int numRenderFormats = ArraySize(RenderTargetFormats); + unsigned int numDepthFormats = ArraySize(DepthStencilFormats); + (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats]; + int numConfigs = 0; + + for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) + { + for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) + { + DXGI_FORMAT renderTargetFormat = RenderTargetFormats[formatIndex]; + + UINT formatSupport = 0; + HRESULT result = mDevice->CheckFormatSupport(renderTargetFormat, &formatSupport); + + if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) + { + DXGI_FORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex]; + + bool depthStencilFormatOK = true; + + if (depthStencilFormat != DXGI_FORMAT_UNKNOWN) + { + UINT formatSupport = 0; + result = mDevice->CheckFormatSupport(depthStencilFormat, &formatSupport); + depthStencilFormatOK = SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL); + } + + if (depthStencilFormatOK) + { + ConfigDesc newConfig; + newConfig.renderTargetFormat = d3d11_gl::ConvertBackBufferFormat(renderTargetFormat); + newConfig.depthStencilFormat = d3d11_gl::ConvertDepthStencilFormat(depthStencilFormat); + newConfig.multiSample = 0; // FIXME: enumerate multi-sampling + newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast + + (*configDescList)[numConfigs++] = newConfig; + } + } + } + } + + return numConfigs; +} + +void Renderer11::deleteConfigs(ConfigDesc *configDescList) +{ + delete [] (configDescList); +} + +void Renderer11::sync(bool block) +{ + if (block) + { + HRESULT result; + + if (!mSyncQuery) + { + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = D3D11_QUERY_EVENT; + queryDesc.MiscFlags = 0; + + result = mDevice->CreateQuery(&queryDesc, &mSyncQuery); + ASSERT(SUCCEEDED(result)); + } + + mDeviceContext->End(mSyncQuery); + mDeviceContext->Flush(); + + do + { + result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); + + // Keep polling, but allow other threads to do something useful first + Sleep(0); + + if (testDeviceLost(true)) + { + return; + } + } + while (result == S_FALSE); + } + else + { + mDeviceContext->Flush(); + } +} + +SwapChain *Renderer11::createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) +{ + return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat); +} + +void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) +{ + if (type == gl::SAMPLER_PIXEL) + { + if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS) + { + ERR("Pixel shader sampler index %i is not valid.", index); + return; + } + + if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) + { + ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState); + + if (!dxSamplerState) + { + ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default" + "sampler state for pixel shaders at slot %i.", index); + } + + mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState); + + mCurPixelSamplerStates[index] = samplerState; + } + + mForceSetPixelSamplerStates[index] = false; + } + else if (type == gl::SAMPLER_VERTEX) + { + if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) + { + ERR("Vertex shader sampler index %i is not valid.", index); + return; + } + + if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) + { + ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState); + + if (!dxSamplerState) + { + ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default" + "sampler state for vertex shaders at slot %i.", index); + } + + mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState); + + mCurVertexSamplerStates[index] = samplerState; + } + + mForceSetVertexSamplerStates[index] = false; + } + else UNREACHABLE(); +} + +void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture) +{ + ID3D11ShaderResourceView *textureSRV = NULL; + unsigned int serial = 0; + bool forceSetTexture = false; + + if (texture) + { + TextureStorageInterface *texStorage = texture->getNativeTexture(); + if (texStorage) + { + TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance()); + textureSRV = storage11->getSRV(); + } + + // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly + // missing the shader resource view + ASSERT(textureSRV != NULL); + + serial = texture->getTextureSerial(); + forceSetTexture = texture->hasDirtyImages(); + } + + if (type == gl::SAMPLER_PIXEL) + { + if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS) + { + ERR("Pixel shader sampler index %i is not valid.", index); + return; + } + + if (forceSetTexture || mCurPixelTextureSerials[index] != serial) + { + mDeviceContext->PSSetShaderResources(index, 1, &textureSRV); + } + + mCurPixelTextureSerials[index] = serial; + } + else if (type == gl::SAMPLER_VERTEX) + { + if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) + { + ERR("Vertex shader sampler index %i is not valid.", index); + return; + } + + if (forceSetTexture || mCurVertexTextureSerials[index] != serial) + { + mDeviceContext->VSSetShaderResources(index, 1, &textureSRV); + } + + mCurVertexTextureSerials[index] = serial; + } + else UNREACHABLE(); +} + +void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) +{ + if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0) + { + ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mScissorEnabled, + mCurDepthSize); + if (!dxRasterState) + { + ERR("NULL rasterizer state returned by RenderStateCache::getRasterizerState, setting the default" + "rasterizer state."); + } + + mDeviceContext->RSSetState(dxRasterState); + + mCurRasterState = rasterState; + } + + mForceSetRasterState = false; +} + +void Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, + unsigned int sampleMask) +{ + if (mForceSetBlendState || + memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 || + memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0 || + sampleMask != mCurSampleMask) + { + ID3D11BlendState *dxBlendState = mStateCache.getBlendState(framebuffer, blendState); + if (!dxBlendState) + { + ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default " + "blend state."); + } + + float blendColors[4] = {0.0f}; + if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && + blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) + { + blendColors[0] = blendColor.red; + blendColors[1] = blendColor.green; + blendColors[2] = blendColor.blue; + blendColors[3] = blendColor.alpha; + } + else + { + blendColors[0] = blendColor.alpha; + blendColors[1] = blendColor.alpha; + blendColors[2] = blendColor.alpha; + blendColors[3] = blendColor.alpha; + } + + mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask); + + mCurBlendState = blendState; + mCurBlendColor = blendColor; + mCurSampleMask = sampleMask; + } + + mForceSetBlendState = false; +} + +void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW) +{ + if (mForceSetDepthStencilState || + memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 || + stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef) + { + if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || + stencilRef != stencilBackRef || + depthStencilState.stencilMask != depthStencilState.stencilBackMask) + { + ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are " + "invalid under WebGL."); + return gl::error(GL_INVALID_OPERATION); + } + + ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState); + if (!dxDepthStencilState) + { + ERR("NULL depth stencil state returned by RenderStateCache::getDepthStencilState, " + "setting the default depth stencil state."); + } + + mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, static_cast(stencilRef)); + + mCurDepthStencilState = depthStencilState; + mCurStencilRef = stencilRef; + mCurStencilBackRef = stencilBackRef; + } + + mForceSetDepthStencilState = false; +} + +void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) +{ + if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || + enabled != mScissorEnabled) + { + if (enabled) + { + D3D11_RECT rect; + rect.left = std::max(0, scissor.x); + rect.top = std::max(0, scissor.y); + rect.right = scissor.x + std::max(0, scissor.width); + rect.bottom = scissor.y + std::max(0, scissor.height); + + mDeviceContext->RSSetScissorRects(1, &rect); + } + + if (enabled != mScissorEnabled) + { + mForceSetRasterState = true; + } + + mCurScissor = scissor; + mScissorEnabled = enabled; + } + + mForceSetScissor = false; +} + +bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport) +{ + gl::Rectangle actualViewport = viewport; + float actualZNear = gl::clamp01(zNear); + float actualZFar = gl::clamp01(zFar); + if (ignoreViewport) + { + actualViewport.x = 0; + actualViewport.y = 0; + actualViewport.width = mRenderTargetDesc.width; + actualViewport.height = mRenderTargetDesc.height; + actualZNear = 0.0f; + actualZFar = 1.0f; + } + + // Get D3D viewport bounds, which depends on the feature level + const Range& viewportBounds = getViewportBounds(); + + // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds + D3D11_VIEWPORT dxViewport; + dxViewport.TopLeftX = gl::clamp(actualViewport.x, viewportBounds.start, viewportBounds.end); + dxViewport.TopLeftY = gl::clamp(actualViewport.y, viewportBounds.start, viewportBounds.end); + dxViewport.Width = gl::clamp(actualViewport.width, 0, getMaxViewportDimension()); + dxViewport.Height = gl::clamp(actualViewport.height, 0, getMaxViewportDimension()); + dxViewport.Width = std::min((int)dxViewport.Width, viewportBounds.end - static_cast(dxViewport.TopLeftX)); + dxViewport.Height = std::min((int)dxViewport.Height, viewportBounds.end - static_cast(dxViewport.TopLeftY)); + dxViewport.MinDepth = actualZNear; + dxViewport.MaxDepth = actualZFar; + + if (dxViewport.Width <= 0 || dxViewport.Height <= 0) + { + return false; // Nothing to render + } + + bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || + actualZNear != mCurNear || actualZFar != mCurFar; + + if (viewportChanged) + { + mDeviceContext->RSSetViewports(1, &dxViewport); + + mCurViewport = actualViewport; + mCurNear = actualZNear; + mCurFar = actualZFar; + + mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f; + mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f; + mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); + mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); + + mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f; + mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f; + + mVertexConstants.depthRange[0] = actualZNear; + mVertexConstants.depthRange[1] = actualZFar; + mVertexConstants.depthRange[2] = actualZFar - actualZNear; + + mPixelConstants.depthRange[0] = actualZNear; + mPixelConstants.depthRange[1] = actualZFar; + mPixelConstants.depthRange[2] = actualZFar - actualZNear; + } + + mForceSetViewport = false; + return true; +} + +bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) +{ + D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; + + GLsizei minCount = 0; + + switch (mode) + { + case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; minCount = 1; break; + case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; minCount = 2; break; + case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; + case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; + case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; + case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; minCount = 3; break; + // emulate fans via rewriting index buffer + case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; + default: + return gl::error(GL_INVALID_ENUM, false); + } + + if (primitiveTopology != mCurrentPrimitiveTopology) + { + mDeviceContext->IASetPrimitiveTopology(primitiveTopology); + mCurrentPrimitiveTopology = primitiveTopology; + } + + return count >= minCount; +} + +bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) +{ + // Get the color render buffer and serial + // Also extract the render target dimensions and view + unsigned int renderTargetWidth = 0; + unsigned int renderTargetHeight = 0; + GLenum renderTargetFormat = 0; + unsigned int renderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {0}; + ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; + bool missingColorRenderTarget = true; + + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + const GLenum drawBufferState = framebuffer->getDrawBufferState(colorAttachment); + + if (framebuffer->getColorbufferType(colorAttachment) != GL_NONE && drawBufferState != GL_NONE) + { + // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order) + ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment)); + + gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(colorAttachment); + + if (!colorbuffer) + { + ERR("render target pointer unexpectedly null."); + return false; + } + + // check for zero-sized default framebuffer, which is a special case. + // in this case we do not wish to modify any state and just silently return false. + // this will not report any gl error but will cause the calling method to return. + if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) + { + return false; + } + + renderTargetSerials[colorAttachment] = colorbuffer->getSerial(); + + // Extract the render target dimensions and view + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + if (!renderTarget) + { + ERR("render target pointer unexpectedly null."); + return false; + } + + framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView(); + if (!framebufferRTVs[colorAttachment]) + { + ERR("render target view pointer unexpectedly null."); + return false; + } + + if (missingColorRenderTarget) + { + renderTargetWidth = colorbuffer->getWidth(); + renderTargetHeight = colorbuffer->getHeight(); + renderTargetFormat = colorbuffer->getActualFormat(); + missingColorRenderTarget = false; + } + +#ifdef _DEBUG + // Workaround for Debug SETSHADERRESOURCES_HAZARD D3D11 warnings + for (unsigned int vertexSerialIndex = 0; vertexSerialIndex < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; vertexSerialIndex++) + { + if (colorbuffer->getTextureSerial() != 0 && mCurVertexTextureSerials[vertexSerialIndex] == colorbuffer->getTextureSerial()) + { + setTexture(gl::SAMPLER_VERTEX, vertexSerialIndex, NULL); + } + } + + for (unsigned int pixelSerialIndex = 0; pixelSerialIndex < gl::MAX_TEXTURE_IMAGE_UNITS; pixelSerialIndex++) + { + if (colorbuffer->getTextureSerial() != 0 && mCurPixelTextureSerials[pixelSerialIndex] == colorbuffer->getTextureSerial()) + { + setTexture(gl::SAMPLER_PIXEL, pixelSerialIndex, NULL); + } + } +#endif + } + } + + // Get the depth stencil render buffer and serials + gl::Renderbuffer *depthStencil = NULL; + unsigned int depthbufferSerial = 0; + unsigned int stencilbufferSerial = 0; + if (framebuffer->getDepthbufferType() != GL_NONE) + { + depthStencil = framebuffer->getDepthbuffer(); + if (!depthStencil) + { + ERR("Depth stencil pointer unexpectedly null."); + SafeRelease(framebufferRTVs); + return false; + } + + depthbufferSerial = depthStencil->getSerial(); + } + else if (framebuffer->getStencilbufferType() != GL_NONE) + { + depthStencil = framebuffer->getStencilbuffer(); + if (!depthStencil) + { + ERR("Depth stencil pointer unexpectedly null."); + SafeRelease(framebufferRTVs); + return false; + } + + stencilbufferSerial = depthStencil->getSerial(); + } + + // Extract the depth stencil sizes and view + unsigned int depthSize = 0; + unsigned int stencilSize = 0; + ID3D11DepthStencilView* framebufferDSV = NULL; + if (depthStencil) + { + RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getDepthStencil()); + if (!depthStencilRenderTarget) + { + ERR("render target pointer unexpectedly null."); + SafeRelease(framebufferRTVs); + return false; + } + + framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); + if (!framebufferDSV) + { + ERR("depth stencil view pointer unexpectedly null."); + SafeRelease(framebufferRTVs); + return false; + } + + // If there is no render buffer, the width, height and format values come from + // the depth stencil + if (missingColorRenderTarget) + { + renderTargetWidth = depthStencil->getWidth(); + renderTargetHeight = depthStencil->getHeight(); + renderTargetFormat = depthStencil->getActualFormat(); + } + + depthSize = depthStencil->getDepthSize(); + stencilSize = depthStencil->getStencilSize(); + } + + // Apply the render target and depth stencil + if (!mRenderTargetDescInitialized || !mDepthStencilInitialized || + memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 || + depthbufferSerial != mAppliedDepthbufferSerial || + stencilbufferSerial != mAppliedStencilbufferSerial) + { + mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), framebufferRTVs, framebufferDSV); + + mRenderTargetDesc.width = renderTargetWidth; + mRenderTargetDesc.height = renderTargetHeight; + mRenderTargetDesc.format = renderTargetFormat; + mForceSetViewport = true; + mForceSetScissor = true; + + if (!mDepthStencilInitialized || depthSize != mCurDepthSize) + { + mCurDepthSize = depthSize; + mForceSetRasterState = true; + } + + mCurStencilSize = stencilSize; + + for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) + { + mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex]; + } + mAppliedDepthbufferSerial = depthbufferSerial; + mAppliedStencilbufferSerial = stencilbufferSerial; + mRenderTargetDescInitialized = true; + mDepthStencilInitialized = true; + } + + return true; +} + +GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) +{ + TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; + GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances); + if (err != GL_NO_ERROR) + { + return err; + } + + return mInputLayoutCache.applyVertexBuffers(attributes, programBinary); +} + +GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) +{ + GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); + + if (err == GL_NO_ERROR) + { + if (indexInfo->storage) + { + if (indexInfo->serial != mAppliedStorageIBSerial || indexInfo->startOffset != mAppliedIBOffset) + { + BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage); + IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); + + mDeviceContext->IASetIndexBuffer(storage->getBuffer(BUFFER_USAGE_INDEX), indexBuffer->getIndexFormat(), indexInfo->startOffset); + + mAppliedIBSerial = 0; + mAppliedStorageIBSerial = storage->getSerial(); + mAppliedIBOffset = indexInfo->startOffset; + } + } + else if (indexInfo->serial != mAppliedIBSerial || indexInfo->startOffset != mAppliedIBOffset) + { + IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); + + mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset); + + mAppliedIBSerial = indexInfo->serial; + mAppliedStorageIBSerial = 0; + mAppliedIBOffset = indexInfo->startOffset; + } + } + + return err; +} + +void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances) +{ + if (mode == GL_LINE_LOOP) + { + drawLineLoop(count, GL_NONE, NULL, 0, NULL); + } + else if (mode == GL_TRIANGLE_FAN) + { + drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances); + } + else if (instances > 0) + { + mDeviceContext->DrawInstanced(count, instances, 0, 0); + } + else + { + mDeviceContext->Draw(count, 0); + } +} + +void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) +{ + if (mode == GL_LINE_LOOP) + { + drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer); + } + else if (mode == GL_TRIANGLE_FAN) + { + drawTriangleFan(count, type, indices, indexInfo.minIndex, elementArrayBuffer, instances); + } + else if (instances > 0) + { + mDeviceContext->DrawIndexedInstanced(count, instances, 0, -static_cast(indexInfo.minIndex), 0); + } + else + { + mDeviceContext->DrawIndexed(count, 0, -static_cast(indexInfo.minIndex)); + } +} + +void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +{ + // Get the raw indices for an indexed draw + if (type != GL_NONE && elementArrayBuffer) + { + gl::Buffer *indexBuffer = elementArrayBuffer; + BufferStorage *storage = indexBuffer->getStorage(); + intptr_t offset = reinterpret_cast(indices); + indices = static_cast(storage->getData()) + offset; + } + + if (!mLineLoopIB) + { + mLineLoopIB = new StreamingIndexBufferInterface(this); + if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) + { + delete mLineLoopIB; + mLineLoopIB = NULL; + + ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + // Checked by Renderer11::applyPrimitiveType + ASSERT(count >= 0); + + if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned int))) + { + ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); + return gl::error(GL_OUT_OF_MEMORY); + } + + const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned int); + if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) + { + ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + void* mappedMemory = NULL; + unsigned int offset; + if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) + { + ERR("Could not map index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + unsigned int *data = reinterpret_cast(mappedMemory); + unsigned int indexBufferOffset = offset; + + switch (type) + { + case GL_NONE: // Non-indexed draw + for (int i = 0; i < count; i++) + { + data[i] = i; + } + data[count] = 0; + break; + case GL_UNSIGNED_BYTE: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_SHORT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_INT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + default: UNREACHABLE(); + } + + if (!mLineLoopIB->unmapBuffer()) + { + ERR("Could not unmap index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + if (mAppliedIBSerial != mLineLoopIB->getSerial() || mAppliedIBOffset != indexBufferOffset) + { + IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer()); + + mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); + mAppliedIBSerial = mLineLoopIB->getSerial(); + mAppliedStorageIBSerial = 0; + mAppliedIBOffset = indexBufferOffset; + } + + mDeviceContext->DrawIndexed(count + 1, 0, -minIndex); +} + +void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances) +{ + // Get the raw indices for an indexed draw + if (type != GL_NONE && elementArrayBuffer) + { + gl::Buffer *indexBuffer = elementArrayBuffer; + BufferStorage *storage = indexBuffer->getStorage(); + intptr_t offset = reinterpret_cast(indices); + indices = static_cast(storage->getData()) + offset; + } + + if (!mTriangleFanIB) + { + mTriangleFanIB = new StreamingIndexBufferInterface(this); + if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) + { + delete mTriangleFanIB; + mTriangleFanIB = NULL; + + ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + // Checked by Renderer11::applyPrimitiveType + ASSERT(count >= 3); + + const unsigned int numTris = count - 2; + + if (numTris > (std::numeric_limits::max() / (sizeof(unsigned int) * 3))) + { + ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required."); + return gl::error(GL_OUT_OF_MEMORY); + } + + const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int); + if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) + { + ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN."); + return gl::error(GL_OUT_OF_MEMORY); + } + + void* mappedMemory = NULL; + unsigned int offset; + if (!mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) + { + ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN."); + return gl::error(GL_OUT_OF_MEMORY); + } + + unsigned int *data = reinterpret_cast(mappedMemory); + unsigned int indexBufferOffset = offset; + + switch (type) + { + case GL_NONE: // Non-indexed draw + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = 0; + data[i*3 + 1] = i + 1; + data[i*3 + 2] = i + 2; + } + break; + case GL_UNSIGNED_BYTE: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + case GL_UNSIGNED_SHORT: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + case GL_UNSIGNED_INT: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + default: UNREACHABLE(); + } + + if (!mTriangleFanIB->unmapBuffer()) + { + ERR("Could not unmap scratch index buffer for GL_TRIANGLE_FAN."); + return gl::error(GL_OUT_OF_MEMORY); + } + + if (mAppliedIBSerial != mTriangleFanIB->getSerial() || mAppliedIBOffset != indexBufferOffset) + { + IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer()); + + mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); + mAppliedIBSerial = mTriangleFanIB->getSerial(); + mAppliedStorageIBSerial = 0; + mAppliedIBOffset = indexBufferOffset; + } + + if (instances > 0) + { + mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0); + } + else + { + mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex); + } +} + +void Renderer11::applyShaders(gl::ProgramBinary *programBinary) +{ + unsigned int programBinarySerial = programBinary->getSerial(); + const bool updateProgramState = (programBinarySerial != mAppliedProgramBinarySerial); + + if (updateProgramState) + { + ShaderExecutable *vertexExe = programBinary->getVertexExecutable(); + ShaderExecutable *pixelExe = programBinary->getPixelExecutable(); + + ID3D11VertexShader *vertexShader = NULL; + if (vertexExe) vertexShader = ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader(); + + ID3D11PixelShader *pixelShader = NULL; + if (pixelExe) pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader(); + + mDeviceContext->PSSetShader(pixelShader, NULL, 0); + mDeviceContext->VSSetShader(vertexShader, NULL, 0); + + programBinary->dirtyAllUniforms(); + + mAppliedProgramBinarySerial = programBinarySerial; + } + + // Only use the geometry shader currently for point sprite drawing + const bool usesGeometryShader = (programBinary->usesGeometryShader() && mCurRasterState.pointDrawMode); + + if (updateProgramState || usesGeometryShader != mIsGeometryShaderActive) + { + if (usesGeometryShader) + { + ShaderExecutable *geometryExe = programBinary->getGeometryExecutable(); + ID3D11GeometryShader *geometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader(); + mDeviceContext->GSSetShader(geometryShader, NULL, 0); + } + else + { + mDeviceContext->GSSetShader(NULL, NULL, 0); + } + + mIsGeometryShaderActive = usesGeometryShader; + } +} + +void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) +{ + ShaderExecutable11 *vertexExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable()); + ShaderExecutable11 *pixelExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getPixelExecutable()); + + unsigned int totalRegisterCountVS = 0; + unsigned int totalRegisterCountPS = 0; + + bool vertexUniformsDirty = false; + bool pixelUniformsDirty = false; + + for (gl::UniformArray::const_iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++) + { + const gl::Uniform *uniform = *uniform_iterator; + + if (uniform->vsRegisterIndex >= 0) + { + totalRegisterCountVS += uniform->registerCount; + vertexUniformsDirty = vertexUniformsDirty || uniform->dirty; + } + + if (uniform->psRegisterIndex >= 0) + { + totalRegisterCountPS += uniform->registerCount; + pixelUniformsDirty = pixelUniformsDirty || uniform->dirty; + } + } + + ID3D11Buffer *vertexConstantBuffer = vertexExecutable->getConstantBuffer(mDevice, totalRegisterCountVS); + ID3D11Buffer *pixelConstantBuffer = pixelExecutable->getConstantBuffer(mDevice, totalRegisterCountPS); + + float (*mapVS)[4] = NULL; + float (*mapPS)[4] = NULL; + + if (totalRegisterCountVS > 0 && vertexUniformsDirty) + { + D3D11_MAPPED_SUBRESOURCE map = {0}; + HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + ASSERT(SUCCEEDED(result)); + mapVS = (float(*)[4])map.pData; + } + + if (totalRegisterCountPS > 0 && pixelUniformsDirty) + { + D3D11_MAPPED_SUBRESOURCE map = {0}; + HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + ASSERT(SUCCEEDED(result)); + mapPS = (float(*)[4])map.pData; + } + + for (gl::UniformArray::iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++) + { + gl::Uniform *uniform = *uniform_iterator; + + if (uniform->type != GL_SAMPLER_2D && uniform->type != GL_SAMPLER_CUBE) + { + if (uniform->vsRegisterIndex >= 0 && mapVS) + { + memcpy(mapVS + uniform->vsRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4])); + } + + if (uniform->psRegisterIndex >= 0 && mapPS) + { + memcpy(mapPS + uniform->psRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4])); + } + } + + uniform->dirty = false; + } + + if (mapVS) + { + mDeviceContext->Unmap(vertexConstantBuffer, 0); + } + + if (mapPS) + { + mDeviceContext->Unmap(pixelConstantBuffer, 0); + } + + if (mCurrentVertexConstantBuffer != vertexConstantBuffer) + { + mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer); + mCurrentVertexConstantBuffer = vertexConstantBuffer; + } + + if (mCurrentPixelConstantBuffer != pixelConstantBuffer) + { + mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer); + mCurrentPixelConstantBuffer = pixelConstantBuffer; + } + + // Driver uniforms + if (!mDriverConstantBufferVS) + { + D3D11_BUFFER_DESC constantBufferDescription = {0}; + constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants); + constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; + constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantBufferDescription.CPUAccessFlags = 0; + constantBufferDescription.MiscFlags = 0; + constantBufferDescription.StructureByteStride = 0; + + HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS); + ASSERT(SUCCEEDED(result)); + + mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS); + } + + if (!mDriverConstantBufferPS) + { + D3D11_BUFFER_DESC constantBufferDescription = {0}; + constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants); + constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; + constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantBufferDescription.CPUAccessFlags = 0; + constantBufferDescription.MiscFlags = 0; + constantBufferDescription.StructureByteStride = 0; + + HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS); + ASSERT(SUCCEEDED(result)); + + mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS); + } + + if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0) + { + mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0); + memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants)); + } + + if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0) + { + mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0); + memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants)); + } + + // needed for the point sprite geometry shader + if (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0 && mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) + { + mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); + mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; + } +} + +void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) +{ + gl::Renderbuffer *firstRenderbuffer = frameBuffer->getFirstColorbuffer(); + GLenum internalFormat = firstRenderbuffer ? firstRenderbuffer->getInternalFormat() : GL_NONE; + + bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) && + ((!clearParams.colorMaskRed && gl::GetRedSize(internalFormat) > 0) || + (!clearParams.colorMaskGreen && gl::GetGreenSize(internalFormat) > 0) || + (!clearParams.colorMaskBlue && gl::GetBlueSize(internalFormat) > 0) || + (!clearParams.colorMaskAlpha && gl::GetAlphaSize(internalFormat) > 0)); + + unsigned int stencilUnmasked = 0x0; + if (frameBuffer->hasStencil()) + { + unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat()); + stencilUnmasked = (0x1 << stencilSize) - 1; + } + bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) && + (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; + + bool needScissoredClear = mScissorEnabled && (mCurScissor.x > 0 || mCurScissor.y > 0 || + mCurScissor.x + mCurScissor.width < mRenderTargetDesc.width || + mCurScissor.y + mCurScissor.height < mRenderTargetDesc.height); + + if (needMaskedColorClear || needMaskedStencilClear || needScissoredClear) + { + maskedClear(clearParams, frameBuffer); + } + else + { + if (clearParams.mask & GL_COLOR_BUFFER_BIT) + { + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + if (frameBuffer->isEnabledColorAttachment(colorAttachment)) + { + gl::Renderbuffer *renderbufferObject = frameBuffer->getColorbuffer(colorAttachment); + if (renderbufferObject) + { + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget()); + if (!renderTarget) + { + ERR("render target pointer unexpectedly null."); + return; + } + + ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); + if (!framebufferRTV) + { + ERR("render target view pointer unexpectedly null."); + return; + } + + GLenum format = renderbufferObject->getInternalFormat(); + + const float clearValues[4] = { (gl::GetRedSize(format) > 0) ? clearParams.colorClearValue.red : 0.0f, + (gl::GetGreenSize(format) > 0) ? clearParams.colorClearValue.green : 0.0f, + (gl::GetBlueSize(format) > 0) ? clearParams.colorClearValue.blue : 0.0f, + (gl::GetAlphaSize(format) > 0) ? clearParams.colorClearValue.alpha : 1.0f }; + mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues); + } + } + } + } + if (clearParams.mask & GL_DEPTH_BUFFER_BIT || clearParams.mask & GL_STENCIL_BUFFER_BIT) + { + gl::Renderbuffer *renderbufferObject = frameBuffer->getDepthOrStencilbuffer(); + if (renderbufferObject) + { + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getDepthStencil()); + if (!renderTarget) + { + ERR("render target pointer unexpectedly null."); + return; + } + + ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); + if (!framebufferDSV) + { + ERR("depth stencil view pointer unexpectedly null."); + return; + } + + UINT clearFlags = 0; + if (clearParams.mask & GL_DEPTH_BUFFER_BIT) + { + clearFlags |= D3D11_CLEAR_DEPTH; + } + if (clearParams.mask & GL_STENCIL_BUFFER_BIT) + { + clearFlags |= D3D11_CLEAR_STENCIL; + } + + float depthClear = gl::clamp01(clearParams.depthClearValue); + UINT8 stencilClear = clearParams.stencilClearValue & 0x000000FF; + + mDeviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); + } + } + } +} + +void Renderer11::maskedClear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) +{ + HRESULT result; + + if (!mClearResourcesInitialized) + { + ASSERT(!mClearVB && !mClearVS && !mClearSinglePS && !mClearMultiplePS && !mClearScissorRS && !mClearNoScissorRS); + + D3D11_BUFFER_DESC vbDesc; + vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex) * 4; + vbDesc.Usage = D3D11_USAGE_DYNAMIC; + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vbDesc.MiscFlags = 0; + vbDesc.StructureByteStride = 0; + + result = mDevice->CreateBuffer(&vbDesc, NULL, &mClearVB); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mClearVB, "Renderer11 masked clear vertex buffer"); + + D3D11_INPUT_ELEMENT_DESC quadLayout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Clear, sizeof(g_VS_Clear), &mClearIL); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mClearIL, "Renderer11 masked clear input layout"); + + result = mDevice->CreateVertexShader(g_VS_Clear, sizeof(g_VS_Clear), NULL, &mClearVS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mClearVS, "Renderer11 masked clear vertex shader"); + + result = mDevice->CreatePixelShader(g_PS_ClearSingle, sizeof(g_PS_ClearSingle), NULL, &mClearSinglePS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mClearSinglePS, "Renderer11 masked clear pixel shader (1 RT)"); + + result = mDevice->CreatePixelShader(g_PS_ClearMultiple, sizeof(g_PS_ClearMultiple), NULL, &mClearMultiplePS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mClearMultiplePS, "Renderer11 masked clear pixel shader (MRT)"); + + D3D11_RASTERIZER_DESC rsScissorDesc; + rsScissorDesc.FillMode = D3D11_FILL_SOLID; + rsScissorDesc.CullMode = D3D11_CULL_NONE; + rsScissorDesc.FrontCounterClockwise = FALSE; + rsScissorDesc.DepthBias = 0; + rsScissorDesc.DepthBiasClamp = 0.0f; + rsScissorDesc.SlopeScaledDepthBias = 0.0f; + rsScissorDesc.DepthClipEnable = FALSE; + rsScissorDesc.ScissorEnable = TRUE; + rsScissorDesc.MultisampleEnable = FALSE; + rsScissorDesc.AntialiasedLineEnable = FALSE; + + result = mDevice->CreateRasterizerState(&rsScissorDesc, &mClearScissorRS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mClearScissorRS, "Renderer11 masked clear scissor rasterizer state"); + + D3D11_RASTERIZER_DESC rsNoScissorDesc; + rsNoScissorDesc.FillMode = D3D11_FILL_SOLID; + rsNoScissorDesc.CullMode = D3D11_CULL_NONE; + rsNoScissorDesc.FrontCounterClockwise = FALSE; + rsNoScissorDesc.DepthBias = 0; + rsNoScissorDesc.DepthBiasClamp = 0.0f; + rsNoScissorDesc.SlopeScaledDepthBias = 0.0f; + rsNoScissorDesc.DepthClipEnable = FALSE; + rsNoScissorDesc.ScissorEnable = FALSE; + rsNoScissorDesc.MultisampleEnable = FALSE; + rsNoScissorDesc.AntialiasedLineEnable = FALSE; + + result = mDevice->CreateRasterizerState(&rsNoScissorDesc, &mClearNoScissorRS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mClearNoScissorRS, "Renderer11 masked clear no scissor rasterizer state"); + + mClearResourcesInitialized = true; + } + + // Prepare the depth stencil state to write depth values if the depth should be cleared + // and stencil values if the stencil should be cleared + gl::DepthStencilState glDSState; + glDSState.depthTest = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0; + glDSState.depthFunc = GL_ALWAYS; + glDSState.depthMask = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0; + glDSState.stencilTest = (clearParams.mask & GL_STENCIL_BUFFER_BIT) != 0; + glDSState.stencilFunc = GL_ALWAYS; + glDSState.stencilMask = 0; + glDSState.stencilFail = GL_REPLACE; + glDSState.stencilPassDepthFail = GL_REPLACE; + glDSState.stencilPassDepthPass = GL_REPLACE; + glDSState.stencilWritemask = clearParams.stencilWriteMask; + glDSState.stencilBackFunc = GL_ALWAYS; + glDSState.stencilBackMask = 0; + glDSState.stencilBackFail = GL_REPLACE; + glDSState.stencilBackPassDepthFail = GL_REPLACE; + glDSState.stencilBackPassDepthPass = GL_REPLACE; + glDSState.stencilBackWritemask = clearParams.stencilWriteMask; + + int stencilClear = clearParams.stencilClearValue & 0x000000FF; + + ID3D11DepthStencilState *dsState = mStateCache.getDepthStencilState(glDSState); + + // Prepare the blend state to use a write mask if the color buffer should be cleared + gl::BlendState glBlendState; + glBlendState.blend = false; + glBlendState.sourceBlendRGB = GL_ONE; + glBlendState.destBlendRGB = GL_ZERO; + glBlendState.sourceBlendAlpha = GL_ONE; + glBlendState.destBlendAlpha = GL_ZERO; + glBlendState.blendEquationRGB = GL_FUNC_ADD; + glBlendState.blendEquationAlpha = GL_FUNC_ADD; + glBlendState.colorMaskRed = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskRed : false; + glBlendState.colorMaskGreen = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskGreen : false; + glBlendState.colorMaskBlue = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskBlue : false; + glBlendState.colorMaskAlpha = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskAlpha : false; + glBlendState.sampleAlphaToCoverage = false; + glBlendState.dither = false; + + static const float blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + static const UINT sampleMask = 0xFFFFFFFF; + + ID3D11BlendState *blendState = mStateCache.getBlendState(frameBuffer, glBlendState); + + // Set the vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = mDeviceContext->Map(mClearVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Failed to map masked clear vertex buffer, HRESULT: 0x%X.", result); + return; + } + + d3d11::PositionDepthColorVertex *vertices = reinterpret_cast(mappedResource.pData); + + float depthClear = gl::clamp01(clearParams.depthClearValue); + d3d11::SetPositionDepthColorVertex(&vertices[0], -1.0f, 1.0f, depthClear, clearParams.colorClearValue); + d3d11::SetPositionDepthColorVertex(&vertices[1], -1.0f, -1.0f, depthClear, clearParams.colorClearValue); + d3d11::SetPositionDepthColorVertex(&vertices[2], 1.0f, 1.0f, depthClear, clearParams.colorClearValue); + d3d11::SetPositionDepthColorVertex(&vertices[3], 1.0f, -1.0f, depthClear, clearParams.colorClearValue); + + mDeviceContext->Unmap(mClearVB, 0); + + // Apply state + mDeviceContext->OMSetBlendState(blendState, blendFactors, sampleMask); + mDeviceContext->OMSetDepthStencilState(dsState, stencilClear); + mDeviceContext->RSSetState(mScissorEnabled ? mClearScissorRS : mClearNoScissorRS); + + // Apply shaders + ID3D11PixelShader *pixelShader = frameBuffer->usingExtendedDrawBuffers() ? mClearMultiplePS : mClearSinglePS; + + mDeviceContext->IASetInputLayout(mClearIL); + mDeviceContext->VSSetShader(mClearVS, NULL, 0); + mDeviceContext->PSSetShader(pixelShader, NULL, 0); + mDeviceContext->GSSetShader(NULL, NULL, 0); + + // Apply vertex buffer + static UINT stride = sizeof(d3d11::PositionDepthColorVertex); + static UINT startIdx = 0; + mDeviceContext->IASetVertexBuffers(0, 1, &mClearVB, &stride, &startIdx); + mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + // Draw the clear quad + mDeviceContext->Draw(4, 0); + + // Clean up + markAllStateDirty(); +} + +void Renderer11::markAllStateDirty() +{ + for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) + { + mAppliedRenderTargetSerials[rtIndex] = 0; + } + mAppliedDepthbufferSerial = 0; + mAppliedStencilbufferSerial = 0; + mDepthStencilInitialized = false; + mRenderTargetDescInitialized = false; + + for (int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) + { + mForceSetVertexSamplerStates[i] = true; + mCurVertexTextureSerials[i] = 0; + } + for (int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++) + { + mForceSetPixelSamplerStates[i] = true; + mCurPixelTextureSerials[i] = 0; + } + + mForceSetBlendState = true; + mForceSetRasterState = true; + mForceSetDepthStencilState = true; + mForceSetScissor = true; + mForceSetViewport = true; + + mAppliedIBSerial = 0; + mAppliedStorageIBSerial = 0; + mAppliedIBOffset = 0; + + mAppliedProgramBinarySerial = 0; + memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants)); + memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants)); + + mInputLayoutCache.markDirty(); + + mCurrentVertexConstantBuffer = NULL; + mCurrentPixelConstantBuffer = NULL; + mCurrentGeometryConstantBuffer = NULL; + + mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; +} + +void Renderer11::releaseDeviceResources() +{ + mStateCache.clear(); + mInputLayoutCache.clear(); + + delete mVertexDataManager; + mVertexDataManager = NULL; + + delete mIndexDataManager; + mIndexDataManager = NULL; + + delete mLineLoopIB; + mLineLoopIB = NULL; + + delete mTriangleFanIB; + mTriangleFanIB = NULL; + + SafeRelease(mCopyVB); + SafeRelease(mCopySampler); + SafeRelease(mCopyIL); + SafeRelease(mCopyIL); + SafeRelease(mCopyVS); + SafeRelease(mCopyRGBAPS); + SafeRelease(mCopyRGBPS); + SafeRelease(mCopyLumPS); + SafeRelease(mCopyLumAlphaPS); + + mCopyResourcesInitialized = false; + + SafeRelease(mClearVB); + SafeRelease(mClearIL); + SafeRelease(mClearVS); + SafeRelease(mClearSinglePS); + SafeRelease(mClearMultiplePS); + SafeRelease(mClearScissorRS); + SafeRelease(mClearNoScissorRS); + + mClearResourcesInitialized = false; + + SafeRelease(mDriverConstantBufferVS); + SafeRelease(mDriverConstantBufferPS); + SafeRelease(mSyncQuery); +} + +void Renderer11::notifyDeviceLost() +{ + mDeviceLost = true; + mDisplay->notifyDeviceLost(); +} + +bool Renderer11::isDeviceLost() +{ + return mDeviceLost; +} + +// set notify to true to broadcast a message to all contexts of the device loss +bool Renderer11::testDeviceLost(bool notify) +{ + bool isLost = false; + + // GetRemovedReason is used to test if the device is removed + HRESULT result = mDevice->GetDeviceRemovedReason(); + isLost = d3d11::isDeviceLostError(result); + + if (isLost) + { + // Log error if this is a new device lost event + if (mDeviceLost == false) + { + ERR("The D3D11 device was removed: 0x%08X", result); + } + + // ensure we note the device loss -- + // we'll probably get this done again by notifyDeviceLost + // but best to remember it! + // Note that we don't want to clear the device loss status here + // -- this needs to be done by resetDevice + mDeviceLost = true; + if (notify) + { + notifyDeviceLost(); + } + } + + return isLost; +} + +bool Renderer11::testDeviceResettable() +{ + // determine if the device is resettable by creating a dummy device + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); + + if (D3D11CreateDevice == NULL) + { + return false; + } + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, +#if !defined(ANGLE_ENABLE_D3D9) + D3D_FEATURE_LEVEL_9_3, + D3D_FEATURE_LEVEL_9_2, + D3D_FEATURE_LEVEL_9_1, +#endif + }; + + ID3D11Device* dummyDevice; + D3D_FEATURE_LEVEL dummyFeatureLevel; + ID3D11DeviceContext* dummyContext; + + HRESULT result = D3D11CreateDevice(NULL, + D3D_DRIVER_TYPE_HARDWARE, + NULL, + #if defined(_DEBUG) + D3D11_CREATE_DEVICE_DEBUG, + #else + 0, + #endif + featureLevels, + ArraySize(featureLevels), + D3D11_SDK_VERSION, + &dummyDevice, + &dummyFeatureLevel, + &dummyContext); + + if (!mDevice || FAILED(result)) + { + return false; + } + + dummyContext->Release(); + dummyDevice->Release(); + + return true; +} + +void Renderer11::release() +{ + releaseDeviceResources(); + + if (mDxgiFactory) + { + mDxgiFactory->Release(); + mDxgiFactory = NULL; + } + + if (mDxgiAdapter) + { + mDxgiAdapter->Release(); + mDxgiAdapter = NULL; + } + + if (mDeviceContext) + { + mDeviceContext->ClearState(); + mDeviceContext->Flush(); + mDeviceContext->Release(); + mDeviceContext = NULL; + } + + if (mDevice) + { + mDevice->Release(); + mDevice = NULL; + } + + if (mD3d11Module) + { + FreeLibrary(mD3d11Module); + mD3d11Module = NULL; + } + + if (mDxgiModule) + { + FreeLibrary(mDxgiModule); + mDxgiModule = NULL; + } +} + +bool Renderer11::resetDevice() +{ + // recreate everything + release(); + EGLint result = initialize(); + + if (result != EGL_SUCCESS) + { + ERR("Could not reinitialize D3D11 device: %08X", result); + return false; + } + + mDeviceLost = false; + + return true; +} + +DWORD Renderer11::getAdapterVendor() const +{ + return mAdapterDescription.VendorId; +} + +std::string Renderer11::getRendererDescription() const +{ + std::ostringstream rendererString; + + rendererString << mDescription; + rendererString << " Direct3D11"; + + rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel(); + rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel(); + + return rendererString.str(); +} + +GUID Renderer11::getAdapterIdentifier() const +{ + // Use the adapter LUID as our adapter ID + // This number is local to a machine is only guaranteed to be unique between restarts + META_ASSERT(sizeof(LUID) <= sizeof(GUID)); + GUID adapterId = {0}; + memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID)); + return adapterId; +} + +bool Renderer11::getBGRATextureSupport() const +{ + return mBGRATextureSupport; +} + +bool Renderer11::getDXT1TextureSupport() +{ + return mDXT1TextureSupport; +} + +bool Renderer11::getDXT3TextureSupport() +{ + return mDXT3TextureSupport; +} + +bool Renderer11::getDXT5TextureSupport() +{ + return mDXT5TextureSupport; +} + +bool Renderer11::getDepthTextureSupport() const +{ + return mDepthTextureSupport; +} + +bool Renderer11::getFloat32TextureSupport(bool *filtering, bool *renderable) +{ + *renderable = mFloat32RenderSupport; + *filtering = mFloat32FilterSupport; + return mFloat32TextureSupport; +} + +bool Renderer11::getFloat16TextureSupport(bool *filtering, bool *renderable) +{ + *renderable = mFloat16RenderSupport; + *filtering = mFloat16FilterSupport; + return mFloat16TextureSupport; +} + +bool Renderer11::getLuminanceTextureSupport() +{ + return false; +} + +bool Renderer11::getLuminanceAlphaTextureSupport() +{ + return false; +} + +bool Renderer11::getTextureFilterAnisotropySupport() const +{ + return true; +} + +float Renderer11::getTextureMaxAnisotropy() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + return D3D11_MAX_MAXANISOTROPY; + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_MAX_MAXANISOTROPY; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + return 16; + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; + default: UNREACHABLE(); + return 0; + } +} + +bool Renderer11::getEventQuerySupport() +{ + return true; +} + +Range Renderer11::getViewportBounds() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + return Range(D3D11_VIEWPORT_BOUNDS_MIN, D3D11_VIEWPORT_BOUNDS_MAX); + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return Range(D3D10_VIEWPORT_BOUNDS_MIN, D3D10_VIEWPORT_BOUNDS_MAX); + case D3D_FEATURE_LEVEL_9_3: + return Range(D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION * -2, D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2); + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return Range(D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION * -2, D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2); + default: UNREACHABLE(); + return Range(0, 0); + } +} + +unsigned int Renderer11::getMaxVertexTextureImageUnits() const +{ + META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; + default: UNREACHABLE(); + return 0; + } +} + +unsigned int Renderer11::getMaxCombinedTextureImageUnits() const +{ + return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits(); +} + +unsigned int Renderer11::getReservedVertexUniformVectors() const +{ + return 0; // Driver uniforms are stored in a separate constant buffer +} + +unsigned int Renderer11::getReservedFragmentUniformVectors() const +{ + return 0; // Driver uniforms are stored in a separate constant buffer +} + +unsigned int Renderer11::getMaxVertexUniformVectors() const +{ + META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); + ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1); + return MAX_VERTEX_UNIFORM_VECTORS_D3D11; +} + +unsigned int Renderer11::getMaxFragmentUniformVectors() const +{ + META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); + ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1); + return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11; +} + +unsigned int Renderer11::getMaxVaryingVectors() const +{ + META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT); + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + return D3D11_VS_OUTPUT_REGISTER_COUNT; + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_VS_OUTPUT_REGISTER_COUNT; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 8; + default: UNREACHABLE(); + return 0; + } +} + +bool Renderer11::getNonPower2TextureSupport() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return true; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; + default: UNREACHABLE(); + return false; + } +} + +bool Renderer11::getOcclusionQuerySupport() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return true; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + return true; + case D3D_FEATURE_LEVEL_9_1: + return false; + default: UNREACHABLE(); + return false; + } +} + +bool Renderer11::getInstancingSupport() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: + return true; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; + default: UNREACHABLE(); + return false; + } +} + +bool Renderer11::getShareHandleSupport() const +{ + // We only currently support share handles with BGRA surfaces, because + // chrome needs BGRA. Once chrome fixes this, we should always support them. + // PIX doesn't seem to support using share handles, so disable them. + return getBGRATextureSupport() && !gl::perfActive(); +} + +bool Renderer11::getDerivativeInstructionSupport() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return true; + case D3D_FEATURE_LEVEL_9_3: + return true; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; + default: UNREACHABLE(); + return false; + } +} + +bool Renderer11::getPostSubBufferSupport() const +{ + // D3D11 does not support present with dirty rectangles until D3D11.1 and DXGI 1.2. + return false; +} + +int Renderer11::getMajorShaderModel() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5 + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4 + case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4 + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MAJOR_VERSION; // 4 (level 9) + default: UNREACHABLE(); return 0; + } +} + +int Renderer11::getMinorShaderModel() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0 + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1 + case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0 + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MINOR_VERSION; // 0 (level 9) + default: UNREACHABLE(); return 0; + } +} + +float Renderer11::getMaxPointSize() const +{ + // choose a reasonable maximum. we enforce this in the shader. + // (nb: on a Radeon 2600xt, DX9 reports a 256 max point size) + return 1024.0f; +} + +int Renderer11::getMaxViewportDimension() const +{ + // Maximum viewport size must be at least as large as the largest render buffer (or larger). + // In our case return the maximum texture size, which is the maximum render buffer size. + META_ASSERT(D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D11_VIEWPORT_BOUNDS_MAX); + META_ASSERT(D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D10_VIEWPORT_BOUNDS_MAX); + + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 + case D3D_FEATURE_LEVEL_9_3: + return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 + default: UNREACHABLE(); + return 0; + } +} + +int Renderer11::getMaxTextureWidth() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 + case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 + default: UNREACHABLE(); return 0; + } +} + +int Renderer11::getMaxTextureHeight() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 + case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 + default: UNREACHABLE(); return 0; + } +} + +bool Renderer11::get32BitIndexSupport() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + default: UNREACHABLE(); return false; + } +} + +int Renderer11::getMinSwapInterval() const +{ + return 0; +} + +int Renderer11::getMaxSwapInterval() const +{ + return 4; +} + +int Renderer11::getMaxSupportedSamples() const +{ + return mMaxSupportedSamples; +} + +int Renderer11::getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const +{ + if (requested == 0) + { + return 0; + } + + MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); + if (iter != mMultisampleSupportMap.end()) + { + const MultisampleSupportInfo& info = iter->second; + for (unsigned int i = requested - 1; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++) + { + if (info.qualityLevels[i] > 0) + { + return i + 1; + } + } + } + + return -1; +} + +unsigned int Renderer11::getMaxRenderTargets() const +{ + META_ASSERT(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); + META_ASSERT(D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); + META_ASSERT(D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); + META_ASSERT(D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); + + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8 + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: // return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT; // 4 + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: // return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT; // 1 + // Feature level 10.0 and 10.1 cards perform very poorly when the pixel shader + // outputs to multiple RTs that are not bound. + // TODO: Remove pixel shader outputs for render targets that are not bound. + return 1; + default: + UNREACHABLE(); + return 1; + } +} + +bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) +{ + if (source && dest) + { + TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source->getStorageInstance()); + TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest->getStorageInstance()); + + mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture()); + return true; + } + + return false; +} + +bool Renderer11::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) +{ + if (source && dest) + { + TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source->getStorageInstance()); + TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest->getStorageInstance()); + + mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture()); + return true; + } + + return false; +} + +bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) +{ + gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); + if (!colorbuffer) + { + ERR("Failed to retrieve the color buffer from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + if (!sourceRenderTarget) + { + ERR("Failed to retrieve the render target from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); + if (!source) + { + ERR("Failed to retrieve the render target view from the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); + if (!storage11) + { + ERR("Failed to retrieve the texture storage from the destination."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(level)); + if (!destRenderTarget) + { + ERR("Failed to retrieve the render target from the destination storage."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); + if (!dest) + { + ERR("Failed to retrieve the render target view from the destination render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + gl::Rectangle destRect; + destRect.x = xoffset; + destRect.y = yoffset; + destRect.width = sourceRect.width; + destRect.height = sourceRect.height; + + bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), + dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat); + + return ret; +} + +bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) +{ + gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); + if (!colorbuffer) + { + ERR("Failed to retrieve the color buffer from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + if (!sourceRenderTarget) + { + ERR("Failed to retrieve the render target from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); + if (!source) + { + ERR("Failed to retrieve the render target view from the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); + if (!storage11) + { + ERR("Failed to retrieve the texture storage from the destination."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(target, level)); + if (!destRenderTarget) + { + ERR("Failed to retrieve the render target from the destination storage."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); + if (!dest) + { + ERR("Failed to retrieve the render target view from the destination render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + gl::Rectangle destRect; + destRect.x = xoffset; + destRect.y = yoffset; + destRect.width = sourceRect.width; + destRect.height = sourceRect.height; + + bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), + dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat); + + return ret; +} + +bool Renderer11::copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight, + ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat) +{ + HRESULT result; + + if (!mCopyResourcesInitialized) + { + ASSERT(!mCopyVB && !mCopySampler && !mCopyIL && !mCopyVS && !mCopyRGBAPS && !mCopyRGBPS && !mCopyLumPS && !mCopyLumAlphaPS); + + D3D11_BUFFER_DESC vbDesc; + vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; + vbDesc.Usage = D3D11_USAGE_DYNAMIC; + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vbDesc.MiscFlags = 0; + vbDesc.StructureByteStride = 0; + + result = mDevice->CreateBuffer(&vbDesc, NULL, &mCopyVB); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mCopyVB, "Renderer11 copy texture vertex buffer"); + + D3D11_SAMPLER_DESC samplerDesc; + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.MipLODBias = 0.0f; + samplerDesc.MaxAnisotropy = 0; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + samplerDesc.BorderColor[0] = 0.0f; + samplerDesc.BorderColor[1] = 0.0f; + samplerDesc.BorderColor[2] = 0.0f; + samplerDesc.BorderColor[3] = 0.0f; + samplerDesc.MinLOD = 0.0f; + samplerDesc.MaxLOD = mDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_0 ? 0.0f : FLT_MAX; + + result = mDevice->CreateSamplerState(&samplerDesc, &mCopySampler); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mCopySampler, "Renderer11 copy sampler"); + + D3D11_INPUT_ELEMENT_DESC quadLayout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mCopyIL); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mCopyIL, "Renderer11 copy texture input layout"); + + result = mDevice->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mCopyVS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mCopyVS, "Renderer11 copy texture vertex shader"); + + result = mDevice->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mCopyRGBAPS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mCopyRGBAPS, "Renderer11 copy texture RGBA pixel shader"); + + result = mDevice->CreatePixelShader(g_PS_PassthroughRGB, sizeof(g_PS_PassthroughRGB), NULL, &mCopyRGBPS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mCopyRGBPS, "Renderer11 copy texture RGB pixel shader"); + + result = mDevice->CreatePixelShader(g_PS_PassthroughLum, sizeof(g_PS_PassthroughLum), NULL, &mCopyLumPS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mCopyLumPS, "Renderer11 copy texture luminance pixel shader"); + + result = mDevice->CreatePixelShader(g_PS_PassthroughLumAlpha, sizeof(g_PS_PassthroughLumAlpha), NULL, &mCopyLumAlphaPS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mCopyLumAlphaPS, "Renderer11 copy texture luminance alpha pixel shader"); + + mCopyResourcesInitialized = true; + } + + // Verify the source and destination area sizes + if (sourceArea.x < 0 || sourceArea.x + sourceArea.width > static_cast(sourceWidth) || + sourceArea.y < 0 || sourceArea.y + sourceArea.height > static_cast(sourceHeight) || + destArea.x < 0 || destArea.x + destArea.width > static_cast(destWidth) || + destArea.y < 0 || destArea.y + destArea.height > static_cast(destHeight)) + { + return gl::error(GL_INVALID_VALUE, false); + } + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = mDeviceContext->Map(mCopyVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + d3d11::PositionTexCoordVertex *vertices = static_cast(mappedResource.pData); + + // Create a quad in homogeneous coordinates + float x1 = (destArea.x / float(destWidth)) * 2.0f - 1.0f; + float y1 = ((destHeight - destArea.y - destArea.height) / float(destHeight)) * 2.0f - 1.0f; + float x2 = ((destArea.x + destArea.width) / float(destWidth)) * 2.0f - 1.0f; + float y2 = ((destHeight - destArea.y) / float(destHeight)) * 2.0f - 1.0f; + + float u1 = sourceArea.x / float(sourceWidth); + float v1 = sourceArea.y / float(sourceHeight); + float u2 = (sourceArea.x + sourceArea.width) / float(sourceWidth); + float v2 = (sourceArea.y + sourceArea.height) / float(sourceHeight); + + d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2); + d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1); + d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2); + d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1); + + mDeviceContext->Unmap(mCopyVB, 0); + + static UINT stride = sizeof(d3d11::PositionTexCoordVertex); + static UINT startIdx = 0; + mDeviceContext->IASetVertexBuffers(0, 1, &mCopyVB, &stride, &startIdx); + + // Apply state + mDeviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); + mDeviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); + mDeviceContext->RSSetState(NULL); + + // Apply shaders + mDeviceContext->IASetInputLayout(mCopyIL); + mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + mDeviceContext->VSSetShader(mCopyVS, NULL, 0); + + ID3D11PixelShader *ps = NULL; + switch(destFormat) + { + case GL_RGBA: ps = mCopyRGBAPS; break; + case GL_RGB: ps = mCopyRGBPS; break; + case GL_ALPHA: ps = mCopyRGBAPS; break; + case GL_BGRA_EXT: ps = mCopyRGBAPS; break; + case GL_LUMINANCE: ps = mCopyLumPS; break; + case GL_LUMINANCE_ALPHA: ps = mCopyLumAlphaPS; break; + default: UNREACHABLE(); ps = NULL; break; + } + + mDeviceContext->PSSetShader(ps, NULL, 0); + mDeviceContext->GSSetShader(NULL, NULL, 0); + + // Unset the currently bound shader resource to avoid conflicts + static ID3D11ShaderResourceView *const nullSRV = NULL; + mDeviceContext->PSSetShaderResources(0, 1, &nullSRV); + + // Apply render target + setOneTimeRenderTarget(dest); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = destWidth; + viewport.Height = destHeight; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + mDeviceContext->RSSetViewports(1, &viewport); + + // Apply textures + mDeviceContext->PSSetShaderResources(0, 1, &source); + mDeviceContext->PSSetSamplers(0, 1, &mCopySampler); + + // Draw the quad + mDeviceContext->Draw(4, 0); + + // Unbind textures and render targets and vertex buffer + mDeviceContext->PSSetShaderResources(0, 1, &nullSRV); + + unapplyRenderTargets(); + + UINT zero = 0; + ID3D11Buffer *const nullBuffer = NULL; + mDeviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + + markAllStateDirty(); + + return true; +} + +void Renderer11::unapplyRenderTargets() +{ + setOneTimeRenderTarget(NULL); +} + +void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView) +{ + ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; + + rtvArray[0] = renderTargetView; + + mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), rtvArray, NULL); + + // Do not preserve the serial for this one-time-use render target + for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) + { + mAppliedRenderTargetSerials[rtIndex] = 0; + } +} + +RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth) +{ + SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); + RenderTarget11 *renderTarget = NULL; + + if (depth) + { + // Note: depth stencil may be NULL for 0 sized surfaces + renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(), + swapChain11->getDepthStencilTexture(), NULL, + swapChain11->getWidth(), swapChain11->getHeight()); + } + else + { + // Note: render target may be NULL for 0 sized surfaces + renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(), + swapChain11->getOffscreenTexture(), + swapChain11->getRenderTargetShaderResource(), + swapChain11->getWidth(), swapChain11->getHeight()); + } + return renderTarget; +} + +RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) +{ + RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples, depth); + return renderTarget; +} + +ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type) +{ + ShaderExecutable11 *executable = NULL; + + switch (type) + { + case rx::SHADER_VERTEX: + { + ID3D11VertexShader *vshader = NULL; + HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vshader); + ASSERT(SUCCEEDED(result)); + + if (vshader) + { + executable = new ShaderExecutable11(function, length, vshader); + } + } + break; + case rx::SHADER_PIXEL: + { + ID3D11PixelShader *pshader = NULL; + HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pshader); + ASSERT(SUCCEEDED(result)); + + if (pshader) + { + executable = new ShaderExecutable11(function, length, pshader); + } + } + break; + case rx::SHADER_GEOMETRY: + { + ID3D11GeometryShader *gshader = NULL; + HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &gshader); + ASSERT(SUCCEEDED(result)); + + if (gshader) + { + executable = new ShaderExecutable11(function, length, gshader); + } + } + break; + default: + UNREACHABLE(); + break; + } + + return executable; +} + +ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) +{ + std::string profile; + + switch (type) + { + case rx::SHADER_VERTEX: + profile = "vs_4_0"; + break; + case rx::SHADER_PIXEL: + profile = "ps_4_0"; + break; + case rx::SHADER_GEOMETRY: + profile = "gs_4_0"; + break; + default: + UNREACHABLE(); + return NULL; + } + + if (mFeatureLevel == D3D_FEATURE_LEVEL_9_3) + profile += "_level_9_3"; + else if (mFeatureLevel == D3D_FEATURE_LEVEL_9_2 || mFeatureLevel == D3D_FEATURE_LEVEL_9_1) + profile += "_level_9_1"; + + ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile.c_str(), D3DCOMPILE_OPTIMIZATION_LEVEL0, false); + if (!binary) + return NULL; + + ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type); + binary->Release(); + + return executable; +} + +VertexBuffer *Renderer11::createVertexBuffer() +{ + return new VertexBuffer11(this); +} + +IndexBuffer *Renderer11::createIndexBuffer() +{ + return new IndexBuffer11(this); +} + +BufferStorage *Renderer11::createBufferStorage() +{ + return new BufferStorage11(this); +} + +QueryImpl *Renderer11::createQuery(GLenum type) +{ + return new Query11(this, type); +} + +FenceImpl *Renderer11::createFence() +{ + return new Fence11(this); +} + +bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource) +{ + ASSERT(colorbuffer != NULL); + + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + if (renderTarget) + { + *subresourceIndex = renderTarget->getSubresourceIndex(); + + ID3D11RenderTargetView *colorBufferRTV = renderTarget->getRenderTargetView(); + if (colorBufferRTV) + { + ID3D11Resource *textureResource = NULL; + colorBufferRTV->GetResource(&textureResource); + + if (textureResource) + { + HRESULT result = textureResource->QueryInterface(IID_ID3D11Texture2D, (void**)resource); + textureResource->Release(); + + if (SUCCEEDED(result)) + { + return true; + } + else + { + ERR("Failed to extract the ID3D11Texture2D from the render target resource, " + "HRESULT: 0x%X.", result); + } + } + } + } + + return false; +} + +bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, + bool blitRenderTarget, bool blitDepthStencil) +{ + if (blitRenderTarget) + { + gl::Renderbuffer *readBuffer = readTarget->getReadColorbuffer(); + + if (!readBuffer) + { + ERR("Failed to retrieve the read buffer from the read framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget *readRenderTarget = readBuffer->getRenderTarget(); + + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + if (drawTarget->isEnabledColorAttachment(colorAttachment)) + { + gl::Renderbuffer *drawBuffer = drawTarget->getColorbuffer(colorAttachment); + + if (!drawBuffer) + { + ERR("Failed to retrieve the draw buffer from the draw framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget(); + + if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, false)) + { + return false; + } + } + } + } + + if (blitDepthStencil) + { + gl::Renderbuffer *readBuffer = readTarget->getDepthOrStencilbuffer(); + gl::Renderbuffer *drawBuffer = drawTarget->getDepthOrStencilbuffer(); + + if (!readBuffer) + { + ERR("Failed to retrieve the read depth-stencil buffer from the read framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + if (!drawBuffer) + { + ERR("Failed to retrieve the draw depth-stencil buffer from the draw framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget *readRenderTarget = readBuffer->getDepthStencil(); + RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil(); + + if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, true)) + { + return false; + } + } + + return true; +} + +void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, + GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) +{ + ID3D11Texture2D *colorBufferTexture = NULL; + unsigned int subresourceIndex = 0; + + gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); + + if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) + { + gl::Rectangle area; + area.x = x; + area.y = y; + area.width = width; + area.height = height; + + readTextureData(colorBufferTexture, subresourceIndex, area, colorbuffer->getActualFormat(), format, type, outputPitch, + packReverseRowOrder, packAlignment, pixels); + + colorBufferTexture->Release(); + colorBufferTexture = NULL; + } +} + +Image *Renderer11::createImage() +{ + return new Image11(); +} + +void Renderer11::generateMipmap(Image *dest, Image *src) +{ + Image11 *dest11 = Image11::makeImage11(dest); + Image11 *src11 = Image11::makeImage11(src); + Image11::generateMipmap(dest11, src11); +} + +TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain) +{ + SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); + return new TextureStorage11_2D(this, swapChain11); +} + +TextureStorage *Renderer11::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) +{ + return new TextureStorage11_2D(this, levels, internalformat, usage, forceRenderable, width, height); +} + +TextureStorage *Renderer11::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) +{ + return new TextureStorage11_Cube(this, levels, internalformat, usage, forceRenderable, size); +} + +static inline unsigned int getFastPixelCopySize(DXGI_FORMAT sourceFormat, GLenum sourceGLFormat, GLenum destFormat, GLenum destType) +{ + if (sourceFormat == DXGI_FORMAT_A8_UNORM && + destFormat == GL_ALPHA && + destType == GL_UNSIGNED_BYTE) + { + return 1; + } + else if (sourceFormat == DXGI_FORMAT_R8G8B8A8_UNORM && + sourceGLFormat == GL_RGBA8_OES && + destFormat == GL_RGBA && + destType == GL_UNSIGNED_BYTE) + { + return 4; + } + else if (sourceFormat == DXGI_FORMAT_B8G8R8A8_UNORM && + destFormat == GL_BGRA_EXT && + destType == GL_UNSIGNED_BYTE) + { + return 4; + } + else if (sourceFormat == DXGI_FORMAT_R16G16B16A16_FLOAT && + sourceGLFormat == GL_RGBA16F_EXT && + destFormat == GL_RGBA && + destType == GL_HALF_FLOAT_OES) + { + return 8; + } + else if (sourceFormat == DXGI_FORMAT_R32G32B32_FLOAT && + destFormat == GL_RGB && + destType == GL_FLOAT) + { + return 12; + } + else if (sourceFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && + sourceGLFormat == GL_RGBA32F_EXT && + destFormat == GL_RGBA && + destType == GL_FLOAT) + { + return 16; + } + else + { + return 0; + } +} + +static inline void readPixelColor(const unsigned char *data, DXGI_FORMAT format, GLenum glFormat, unsigned int x, + unsigned int y, int inputPitch, gl::Color *outColor) +{ + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + unsigned int rgba = *reinterpret_cast(data + 4 * x + y * inputPitch); + outColor->red = (rgba & 0x000000FF) * (1.0f / 0x000000FF); + outColor->green = (rgba & 0x0000FF00) * (1.0f / 0x0000FF00); + outColor->blue = (rgba & 0x00FF0000) * (1.0f / 0x00FF0000); + + if (gl::GetAlphaSize(glFormat) > 0) + { + outColor->alpha = (rgba & 0xFF000000) * (1.0f / 0xFF000000); + } + else + { + outColor->alpha = 1.0f; + } + } + break; + + case DXGI_FORMAT_A8_UNORM: + { + outColor->red = 0.0f; + outColor->green = 0.0f; + outColor->blue = 0.0f; + outColor->alpha = *(data + x + y * inputPitch) / 255.0f; + } + break; + + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + outColor->red = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 0); + outColor->green = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 1); + outColor->blue = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 2); + + if (gl::GetAlphaSize(glFormat) > 0) + { + outColor->alpha = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 3); + } + else + { + outColor->alpha = 1.0f; + } + } + break; + + case DXGI_FORMAT_R32G32B32_FLOAT: + { + outColor->red = *(reinterpret_cast(data + 12 * x + y * inputPitch) + 0); + outColor->green = *(reinterpret_cast(data + 12 * x + y * inputPitch) + 1); + outColor->blue = *(reinterpret_cast(data + 12 * x + y * inputPitch) + 2); + outColor->alpha = 1.0f; + } + break; + + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + outColor->red = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 0)); + outColor->green = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 1)); + outColor->blue = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 2)); + + if (gl::GetAlphaSize(glFormat) > 0) + { + outColor->alpha = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 3)); + } + else + { + outColor->alpha = 1.0f; + } + } + break; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + { + unsigned int bgra = *reinterpret_cast(data + 4 * x + y * inputPitch); + outColor->red = (bgra & 0x00FF0000) * (1.0f / 0x00FF0000); + outColor->blue = (bgra & 0x000000FF) * (1.0f / 0x000000FF); + outColor->green = (bgra & 0x0000FF00) * (1.0f / 0x0000FF00); + outColor->alpha = (bgra & 0xFF000000) * (1.0f / 0xFF000000); + } + break; + + case DXGI_FORMAT_R8_UNORM: + { + outColor->red = *(data + x + y * inputPitch) / 255.0f; + outColor->green = 0.0f; + outColor->blue = 0.0f; + outColor->alpha = 1.0f; + } + break; + + case DXGI_FORMAT_R8G8_UNORM: + { + unsigned short rg = *reinterpret_cast(data + 2 * x + y * inputPitch); + + outColor->red = (rg & 0xFF00) * (1.0f / 0xFF00); + outColor->green = (rg & 0x00FF) * (1.0f / 0x00FF); + outColor->blue = 0.0f; + outColor->alpha = 1.0f; + } + break; + + case DXGI_FORMAT_R16_FLOAT: + { + outColor->red = gl::float16ToFloat32(*reinterpret_cast(data + 2 * x + y * inputPitch)); + outColor->green = 0.0f; + outColor->blue = 0.0f; + outColor->alpha = 1.0f; + } + break; + + case DXGI_FORMAT_R16G16_FLOAT: + { + outColor->red = gl::float16ToFloat32(*(reinterpret_cast(data + 4 * x + y * inputPitch) + 0)); + outColor->green = gl::float16ToFloat32(*(reinterpret_cast(data + 4 * x + y * inputPitch) + 1)); + outColor->blue = 0.0f; + outColor->alpha = 1.0f; + } + break; + + default: + ERR("ReadPixelColor not implemented for DXGI format %u.", format); + UNIMPLEMENTED(); + break; + } +} + +static inline void writePixelColor(const gl::Color &color, GLenum format, GLenum type, unsigned int x, + unsigned int y, int outputPitch, void *outData) +{ + unsigned char* byteData = reinterpret_cast(outData); + unsigned short* shortData = reinterpret_cast(outData); + + switch (format) + { + case GL_RGBA: + switch (type) + { + case GL_UNSIGNED_BYTE: + byteData[4 * x + y * outputPitch + 0] = static_cast(255 * color.red + 0.5f); + byteData[4 * x + y * outputPitch + 1] = static_cast(255 * color.green + 0.5f); + byteData[4 * x + y * outputPitch + 2] = static_cast(255 * color.blue + 0.5f); + byteData[4 * x + y * outputPitch + 3] = static_cast(255 * color.alpha + 0.5f); + break; + + default: + ERR("WritePixelColor not implemented for format GL_RGBA and type 0x%X.", type); + UNIMPLEMENTED(); + break; + } + break; + + case GL_BGRA_EXT: + switch (type) + { + case GL_UNSIGNED_BYTE: + byteData[4 * x + y * outputPitch + 0] = static_cast(255 * color.blue + 0.5f); + byteData[4 * x + y * outputPitch + 1] = static_cast(255 * color.green + 0.5f); + byteData[4 * x + y * outputPitch + 2] = static_cast(255 * color.red + 0.5f); + byteData[4 * x + y * outputPitch + 3] = static_cast(255 * color.alpha + 0.5f); + break; + + case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: + // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section + // this type is packed as follows: + // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------- + // | 4th | 3rd | 2nd | 1st component | + // -------------------------------------------------------------------------------- + // in the case of BGRA_EXT, B is the first component, G the second, and so forth. + shortData[x + y * outputPitch / sizeof(unsigned short)] = + (static_cast(15 * color.alpha + 0.5f) << 12) | + (static_cast(15 * color.red + 0.5f) << 8) | + (static_cast(15 * color.green + 0.5f) << 4) | + (static_cast(15 * color.blue + 0.5f) << 0); + break; + + case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: + // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section + // this type is packed as follows: + // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------- + // | 4th | 3rd | 2nd | 1st component | + // -------------------------------------------------------------------------------- + // in the case of BGRA_EXT, B is the first component, G the second, and so forth. + shortData[x + y * outputPitch / sizeof(unsigned short)] = + (static_cast( color.alpha + 0.5f) << 15) | + (static_cast(31 * color.red + 0.5f) << 10) | + (static_cast(31 * color.green + 0.5f) << 5) | + (static_cast(31 * color.blue + 0.5f) << 0); + break; + + default: + ERR("WritePixelColor not implemented for format GL_BGRA_EXT and type 0x%X.", type); + UNIMPLEMENTED(); + break; + } + break; + + case GL_RGB: + switch (type) + { + case GL_UNSIGNED_SHORT_5_6_5: + shortData[x + y * outputPitch / sizeof(unsigned short)] = + (static_cast(31 * color.blue + 0.5f) << 0) | + (static_cast(63 * color.green + 0.5f) << 5) | + (static_cast(31 * color.red + 0.5f) << 11); + break; + + case GL_UNSIGNED_BYTE: + byteData[3 * x + y * outputPitch + 0] = static_cast(255 * color.red + 0.5f); + byteData[3 * x + y * outputPitch + 1] = static_cast(255 * color.green + 0.5f); + byteData[3 * x + y * outputPitch + 2] = static_cast(255 * color.blue + 0.5f); + break; + + default: + ERR("WritePixelColor not implemented for format GL_RGB and type 0x%X.", type); + UNIMPLEMENTED(); + break; + } + break; + + default: + ERR("WritePixelColor not implemented for format 0x%X.", format); + UNIMPLEMENTED(); + break; + } +} + +void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, + GLenum sourceFormat, GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder, + GLint packAlignment, void *pixels) +{ + D3D11_TEXTURE2D_DESC textureDesc; + texture->GetDesc(&textureDesc); + + D3D11_TEXTURE2D_DESC stagingDesc; + stagingDesc.Width = area.width; + stagingDesc.Height = area.height; + stagingDesc.MipLevels = 1; + stagingDesc.ArraySize = 1; + stagingDesc.Format = textureDesc.Format; + stagingDesc.SampleDesc.Count = 1; + stagingDesc.SampleDesc.Quality = 0; + stagingDesc.Usage = D3D11_USAGE_STAGING; + stagingDesc.BindFlags = 0; + stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stagingDesc.MiscFlags = 0; + + ID3D11Texture2D* stagingTex = NULL; + HRESULT result = mDevice->CreateTexture2D(&stagingDesc, NULL, &stagingTex); + if (FAILED(result)) + { + ERR("Failed to create staging texture for readPixels, HRESULT: 0x%X.", result); + return; + } + + ID3D11Texture2D* srcTex = NULL; + if (textureDesc.SampleDesc.Count > 1) + { + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = textureDesc.Width; + resolveDesc.Height = textureDesc.Height; + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = textureDesc.Format; + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = D3D11_USAGE_DEFAULT; + resolveDesc.BindFlags = 0; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + result = mDevice->CreateTexture2D(&resolveDesc, NULL, &srcTex); + if (FAILED(result)) + { + ERR("Failed to create resolve texture for readPixels, HRESULT: 0x%X.", result); + stagingTex->Release(); + return; + } + + mDeviceContext->ResolveSubresource(srcTex, 0, texture, subResource, textureDesc.Format); + subResource = 0; + } + else + { + srcTex = texture; + srcTex->AddRef(); + } + + D3D11_BOX srcBox; + srcBox.left = area.x; + srcBox.right = area.x + area.width; + srcBox.top = area.y; + srcBox.bottom = area.y + area.height; + srcBox.front = 0; + srcBox.back = 1; + + mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox); + + srcTex->Release(); + srcTex = NULL; + + D3D11_MAPPED_SUBRESOURCE mapping; + mDeviceContext->Map(stagingTex, 0, D3D11_MAP_READ, 0, &mapping); + + unsigned char *source; + int inputPitch; + if (packReverseRowOrder) + { + source = static_cast(mapping.pData) + mapping.RowPitch * (area.height - 1); + inputPitch = -static_cast(mapping.RowPitch); + } + else + { + source = static_cast(mapping.pData); + inputPitch = static_cast(mapping.RowPitch); + } + + unsigned int fastPixelSize = getFastPixelCopySize(textureDesc.Format, sourceFormat, format, type); + if (fastPixelSize != 0) + { + unsigned char *dest = static_cast(pixels); + for (int j = 0; j < area.height; j++) + { + memcpy(dest + j * outputPitch, source + j * inputPitch, area.width * fastPixelSize); + } + } + else if (textureDesc.Format == DXGI_FORMAT_B8G8R8A8_UNORM && + format == GL_RGBA && + type == GL_UNSIGNED_BYTE) + { + // Fast path for swapping red with blue + unsigned char *dest = static_cast(pixels); + + for (int j = 0; j < area.height; j++) + { + for (int i = 0; i < area.width; i++) + { + unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); + *(unsigned int*)(dest + 4 * i + j * outputPitch) = + (argb & 0xFF00FF00) | // Keep alpha and green + (argb & 0x00FF0000) >> 16 | // Move red to blue + (argb & 0x000000FF) << 16; // Move blue to red + } + } + } + else + { + gl::Color pixelColor; + for (int j = 0; j < area.height; j++) + { + for (int i = 0; i < area.width; i++) + { + readPixelColor(source, textureDesc.Format, sourceFormat, i, j, inputPitch, &pixelColor); + writePixelColor(pixelColor, format, type, i, j, outputPitch, pixels); + } + } + } + + mDeviceContext->Unmap(stagingTex, 0); + + stagingTex->Release(); + stagingTex = NULL; +} + +bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, + RenderTarget *drawRenderTarget, bool wholeBufferCopy) +{ + ASSERT(readRect.width == drawRect.width && readRect.height == drawRect.height); + + RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget); + if (!drawRenderTarget) + { + ERR("Failed to retrieve the draw render target from the draw framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11Texture2D *drawTexture = drawRenderTarget11->getTexture(); + unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); + + RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget); + if (!readRenderTarget) + { + ERR("Failed to retrieve the read render target from the read framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11Texture2D *readTexture = NULL; + unsigned int readSubresource = 0; + if (readRenderTarget->getSamples() > 0) + { + readTexture = resolveMultisampledTexture(readRenderTarget11->getTexture(), readRenderTarget11->getSubresourceIndex()); + readSubresource = 0; + } + else + { + readTexture = readRenderTarget11->getTexture(); + readTexture->AddRef(); + readSubresource = readRenderTarget11->getSubresourceIndex(); + } + + if (!readTexture) + { + ERR("Failed to retrieve the read render target view from the read render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + D3D11_BOX readBox; + readBox.left = readRect.x; + readBox.right = readRect.x + readRect.width; + readBox.top = readRect.y; + readBox.bottom = readRect.y + readRect.height; + readBox.front = 0; + readBox.back = 1; + + // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox + // We also require complete framebuffer copies for depth-stencil blit. + D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox; + + mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, drawRect.x, drawRect.y, 0, + readTexture, readSubresource, pSrcBox); + + SafeRelease(readTexture); + + return true; +} + +ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource) +{ + D3D11_TEXTURE2D_DESC textureDesc; + source->GetDesc(&textureDesc); + + if (textureDesc.SampleDesc.Count > 1) + { + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = textureDesc.Width; + resolveDesc.Height = textureDesc.Height; + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = textureDesc.Format; + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = textureDesc.Usage; + resolveDesc.BindFlags = textureDesc.BindFlags; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + ID3D11Texture2D *resolveTexture = NULL; + HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture); + if (FAILED(result)) + { + ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result); + return NULL; + } + + mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format); + return resolveTexture; + } + else + { + source->AddRef(); + return source; + } +} + +bool Renderer11::getLUID(LUID *adapterLuid) const +{ + adapterLuid->HighPart = 0; + adapterLuid->LowPart = 0; + + if (!mDxgiAdapter) + { + return false; + } + + DXGI_ADAPTER_DESC adapterDesc; + if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc))) + { + return false; + } + + *adapterLuid = adapterDesc.AdapterLuid; + return true; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h new file mode 100644 index 0000000000..a8a722c56c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h @@ -0,0 +1,358 @@ +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer11.h: Defines a back-end specific class for the D3D11 renderer. + +#ifndef LIBGLESV2_RENDERER_RENDERER11_H_ +#define LIBGLESV2_RENDERER_RENDERER11_H_ + +#include "common/angleutils.h" +#include "libGLESv2/angletypes.h" +#include "libGLESv2/mathutil.h" + +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/d3d11/RenderStateCache.h" +#include "libGLESv2/renderer/d3d11/InputLayoutCache.h" +#include "libGLESv2/renderer/RenderTarget.h" + +namespace gl +{ +class Renderbuffer; +} + +namespace rx +{ + +class VertexDataManager; +class IndexDataManager; +class StreamingIndexBufferInterface; + +enum +{ + MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024, + MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024 +}; + +class Renderer11 : public Renderer +{ + public: + Renderer11(egl::Display *display); + virtual ~Renderer11(); + + static Renderer11 *makeRenderer11(Renderer *renderer); + + virtual EGLint initialize(); + virtual bool resetDevice(); + + virtual int generateConfigs(ConfigDesc **configDescList); + virtual void deleteConfigs(ConfigDesc *configDescList); + + virtual void sync(bool block); + + virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + + virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); + virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture); + + virtual void setRasterizerState(const gl::RasterizerState &rasterState); + virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, + unsigned int sampleMask); + virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW); + + virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); + virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport); + + virtual bool applyPrimitiveType(GLenum mode, GLsizei count); + virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer); + virtual void applyShaders(gl::ProgramBinary *programBinary); + virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray); + virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances); + virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); + + virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances); + virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); + + virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); + + virtual void markAllStateDirty(); + + // lost device + void notifyDeviceLost(); + virtual bool isDeviceLost(); + virtual bool testDeviceLost(bool notify); + virtual bool testDeviceResettable(); + + // Renderer capabilities + virtual DWORD getAdapterVendor() const; + virtual std::string getRendererDescription() const; + virtual GUID getAdapterIdentifier() const; + + virtual bool getBGRATextureSupport() const; + virtual bool getDXT1TextureSupport(); + virtual bool getDXT3TextureSupport(); + virtual bool getDXT5TextureSupport(); + virtual bool getEventQuerySupport(); + virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable); + virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable); + virtual bool getLuminanceTextureSupport(); + virtual bool getLuminanceAlphaTextureSupport(); + virtual unsigned int getMaxVertexTextureImageUnits() const; + virtual unsigned int getMaxCombinedTextureImageUnits() const; + virtual unsigned int getReservedVertexUniformVectors() const; + virtual unsigned int getReservedFragmentUniformVectors() const; + virtual unsigned int getMaxVertexUniformVectors() const; + virtual unsigned int getMaxFragmentUniformVectors() const; + virtual unsigned int getMaxVaryingVectors() const; + virtual bool getNonPower2TextureSupport() const; + virtual bool getDepthTextureSupport() const; + virtual bool getOcclusionQuerySupport() const; + virtual bool getInstancingSupport() const; + virtual bool getTextureFilterAnisotropySupport() const; + virtual float getTextureMaxAnisotropy() const; + virtual bool getShareHandleSupport() const; + virtual bool getDerivativeInstructionSupport() const; + virtual bool getPostSubBufferSupport() const; + + virtual int getMajorShaderModel() const; + virtual float getMaxPointSize() const; + virtual int getMaxViewportDimension() const; + virtual int getMaxTextureWidth() const; + virtual int getMaxTextureHeight() const; + virtual bool get32BitIndexSupport() const; + virtual int getMinSwapInterval() const; + virtual int getMaxSwapInterval() const; + + virtual GLsizei getMaxSupportedSamples() const; + int getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const; + + virtual unsigned int getMaxRenderTargets() const; + + // Pixel operations + virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source); + virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source); + + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level); + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level); + + bool copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight, + ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat); + + virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, + bool blitRenderTarget, bool blitDepthStencil); + virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, + GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels); + + // RenderTarget creation + virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); + virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth); + + // Shader operations + virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type); + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround); + + // Image operations + virtual Image *createImage(); + virtual void generateMipmap(Image *dest, Image *source); + virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); + virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); + virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); + + // Buffer creation + virtual VertexBuffer *createVertexBuffer(); + virtual IndexBuffer *createIndexBuffer(); + virtual BufferStorage *createBufferStorage(); + + // Query and Fence creation + virtual QueryImpl *createQuery(GLenum type); + virtual FenceImpl *createFence(); + + // D3D11-renderer specific methods + ID3D11Device *getDevice() { return mDevice; } + ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; + IDXGIFactory *getDxgiFactory() { return mDxgiFactory; }; + D3D_FEATURE_LEVEL getFeatureLevel() { return mFeatureLevel; } + + bool getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource); + void unapplyRenderTargets(); + void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView); + + virtual bool getLUID(LUID *adapterLuid) const; + + private: + DISALLOW_COPY_AND_ASSIGN(Renderer11); + + void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); + void drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances); + + void readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, + GLenum sourceFormat, GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder, + GLint packAlignment, void *pixels); + + void maskedClear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); + rx::Range getViewportBounds() const; + + bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, + RenderTarget *drawRenderTarget, bool wholeBufferCopy); + ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); + + HMODULE mD3d11Module; + HMODULE mDxgiModule; + + bool mDeviceLost; + + void initializeDevice(); + void releaseDeviceResources(); + int getMinorShaderModel() const; + void release(); + + RenderStateCache mStateCache; + + // Support flags + bool mFloat16TextureSupport; + bool mFloat16FilterSupport; + bool mFloat16RenderSupport; + + bool mFloat32TextureSupport; + bool mFloat32FilterSupport; + bool mFloat32RenderSupport; + + bool mDXT1TextureSupport; + bool mDXT3TextureSupport; + bool mDXT5TextureSupport; + + bool mDepthTextureSupport; + + // Multisample format support + struct MultisampleSupportInfo + { + unsigned int qualityLevels[D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT]; + }; + + typedef std::unordered_map > MultisampleSupportMap; + MultisampleSupportMap mMultisampleSupportMap; + + unsigned int mMaxSupportedSamples; + + // current render target states + unsigned int mAppliedRenderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; + unsigned int mAppliedDepthbufferSerial; + unsigned int mAppliedStencilbufferSerial; + bool mDepthStencilInitialized; + bool mRenderTargetDescInitialized; + rx::RenderTarget::Desc mRenderTargetDesc; + unsigned int mCurDepthSize; + unsigned int mCurStencilSize; + + // Currently applied sampler states + bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + gl::SamplerState mCurVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + + bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; + gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; + + // Currently applied textures + unsigned int mCurVertexTextureSerials[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS]; + + // Currently applied blend state + bool mForceSetBlendState; + gl::BlendState mCurBlendState; + gl::Color mCurBlendColor; + unsigned int mCurSampleMask; + + // Currently applied rasterizer state + bool mForceSetRasterState; + gl::RasterizerState mCurRasterState; + + // Currently applied depth stencil state + bool mForceSetDepthStencilState; + gl::DepthStencilState mCurDepthStencilState; + int mCurStencilRef; + int mCurStencilBackRef; + + // Currently applied scissor rectangle + bool mForceSetScissor; + bool mScissorEnabled; + gl::Rectangle mCurScissor; + + // Currently applied viewport + bool mForceSetViewport; + gl::Rectangle mCurViewport; + float mCurNear; + float mCurFar; + + // Currently applied primitive topology + D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology; + + unsigned int mAppliedIBSerial; + unsigned int mAppliedStorageIBSerial; + unsigned int mAppliedIBOffset; + + unsigned int mAppliedProgramBinarySerial; + bool mIsGeometryShaderActive; + + dx_VertexConstants mVertexConstants; + dx_VertexConstants mAppliedVertexConstants; + ID3D11Buffer *mDriverConstantBufferVS; + ID3D11Buffer *mCurrentVertexConstantBuffer; + + dx_PixelConstants mPixelConstants; + dx_PixelConstants mAppliedPixelConstants; + ID3D11Buffer *mDriverConstantBufferPS; + ID3D11Buffer *mCurrentPixelConstantBuffer; + + ID3D11Buffer *mCurrentGeometryConstantBuffer; + + // Vertex, index and input layouts + VertexDataManager *mVertexDataManager; + IndexDataManager *mIndexDataManager; + InputLayoutCache mInputLayoutCache; + + StreamingIndexBufferInterface *mLineLoopIB; + StreamingIndexBufferInterface *mTriangleFanIB; + + // Texture copy resources + bool mCopyResourcesInitialized; + ID3D11Buffer *mCopyVB; + ID3D11SamplerState *mCopySampler; + ID3D11InputLayout *mCopyIL; + ID3D11VertexShader *mCopyVS; + ID3D11PixelShader *mCopyRGBAPS; + ID3D11PixelShader *mCopyRGBPS; + ID3D11PixelShader *mCopyLumPS; + ID3D11PixelShader *mCopyLumAlphaPS; + + // Masked clear resources + bool mClearResourcesInitialized; + ID3D11Buffer *mClearVB; + ID3D11InputLayout *mClearIL; + ID3D11VertexShader *mClearVS; + ID3D11PixelShader *mClearSinglePS; + ID3D11PixelShader *mClearMultiplePS; + ID3D11RasterizerState *mClearScissorRS; + ID3D11RasterizerState *mClearNoScissorRS; + + // Sync query + ID3D11Query *mSyncQuery; + + ID3D11Device *mDevice; + D3D_FEATURE_LEVEL mFeatureLevel; + ID3D11DeviceContext *mDeviceContext; + IDXGIAdapter *mDxgiAdapter; + DXGI_ADAPTER_DESC mAdapterDescription; + char mDescription[128]; + IDXGIFactory *mDxgiFactory; + + // Cached device caps + bool mBGRATextureSupport; +}; + +} +#endif // LIBGLESV2_RENDERER_RENDERER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp new file mode 100644 index 0000000000..2e455e3af5 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp @@ -0,0 +1,109 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader +// executable implementation details. + +#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h" + +#include "common/debug.h" + +namespace rx +{ + +ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable) + : ShaderExecutable(function, length) +{ + mPixelExecutable = executable; + mVertexExecutable = NULL; + mGeometryExecutable = NULL; + + mConstantBuffer = NULL; +} + +ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable) + : ShaderExecutable(function, length) +{ + mVertexExecutable = executable; + mPixelExecutable = NULL; + mGeometryExecutable = NULL; + + mConstantBuffer = NULL; +} + +ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable) + : ShaderExecutable(function, length) +{ + mGeometryExecutable = executable; + mVertexExecutable = NULL; + mPixelExecutable = NULL; + + mConstantBuffer = NULL; +} + +ShaderExecutable11::~ShaderExecutable11() +{ + if (mVertexExecutable) + { + mVertexExecutable->Release(); + } + if (mPixelExecutable) + { + mPixelExecutable->Release(); + } + if (mGeometryExecutable) + { + mGeometryExecutable->Release(); + } + + if (mConstantBuffer) + { + mConstantBuffer->Release(); + } +} + +ShaderExecutable11 *ShaderExecutable11::makeShaderExecutable11(ShaderExecutable *executable) +{ + ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable11*, executable)); + return static_cast(executable); +} + +ID3D11VertexShader *ShaderExecutable11::getVertexShader() const +{ + return mVertexExecutable; +} + +ID3D11PixelShader *ShaderExecutable11::getPixelShader() const +{ + return mPixelExecutable; +} + +ID3D11GeometryShader *ShaderExecutable11::getGeometryShader() const +{ + return mGeometryExecutable; +} + +ID3D11Buffer *ShaderExecutable11::getConstantBuffer(ID3D11Device *device, unsigned int registerCount) +{ + if (!mConstantBuffer && registerCount > 0) + { + D3D11_BUFFER_DESC constantBufferDescription = {0}; + constantBufferDescription.ByteWidth = registerCount * sizeof(float[4]); + constantBufferDescription.Usage = D3D11_USAGE_DYNAMIC; + constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantBufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + constantBufferDescription.MiscFlags = 0; + constantBufferDescription.StructureByteStride = 0; + + HRESULT result = device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer); + ASSERT(SUCCEEDED(result)); + } + + return mConstantBuffer; +} + +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h new file mode 100644 index 0000000000..c6ec1cf7d2 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h @@ -0,0 +1,47 @@ +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderExecutable11.h: Defines a D3D11-specific class to contain shader +// executable implementation details. + +#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ +#define LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ + +#include "libGLESv2/renderer/ShaderExecutable.h" + +namespace rx +{ + +class ShaderExecutable11 : public ShaderExecutable +{ + public: + ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable); + ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable); + ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable); + + virtual ~ShaderExecutable11(); + + static ShaderExecutable11 *makeShaderExecutable11(ShaderExecutable *executable); + + ID3D11PixelShader *getPixelShader() const; + ID3D11VertexShader *getVertexShader() const; + ID3D11GeometryShader *getGeometryShader() const; + + ID3D11Buffer *getConstantBuffer(ID3D11Device *device, unsigned int registerCount); + + private: + DISALLOW_COPY_AND_ASSIGN(ShaderExecutable11); + + ID3D11PixelShader *mPixelExecutable; + ID3D11VertexShader *mVertexExecutable; + ID3D11GeometryShader *mGeometryExecutable; + + ID3D11Buffer *mConstantBuffer; +}; + +} + +#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp new file mode 100644 index 0000000000..bd97d5cff5 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp @@ -0,0 +1,700 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. + +#include "libGLESv2/renderer/d3d11/SwapChain11.h" + +#include "libGLESv2/renderer/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" + +#include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h" +#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h" + +namespace rx +{ + +SwapChain11::SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle, + GLenum backBufferFormat, GLenum depthBufferFormat) + : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) +{ + mSwapChain = NULL; + mBackBufferTexture = NULL; + mBackBufferRTView = NULL; + mOffscreenTexture = NULL; + mOffscreenRTView = NULL; + mOffscreenSRView = NULL; + mDepthStencilTexture = NULL; + mDepthStencilDSView = NULL; + mQuadVB = NULL; + mPassThroughSampler = NULL; + mPassThroughIL = NULL; + mPassThroughVS = NULL; + mPassThroughPS = NULL; + mWidth = -1; + mHeight = -1; + mSwapInterval = 0; + mAppCreatedShareHandle = mShareHandle != NULL; + mPassThroughResourcesInit = false; +} + +SwapChain11::~SwapChain11() +{ + release(); +} + +void SwapChain11::release() +{ + SafeRelease(mSwapChain); + SafeRelease(mBackBufferTexture); + SafeRelease(mBackBufferRTView); + SafeRelease(mOffscreenTexture); + SafeRelease(mOffscreenRTView); + SafeRelease(mOffscreenSRView); + SafeRelease(mDepthStencilTexture); + SafeRelease(mDepthStencilDSView); + SafeRelease(mQuadVB); + SafeRelease(mPassThroughSampler); + SafeRelease(mPassThroughIL); + SafeRelease(mPassThroughVS); + SafeRelease(mPassThroughPS); + + if (!mAppCreatedShareHandle) + { + mShareHandle = NULL; + } +} + +void SwapChain11::releaseOffscreenTexture() +{ + SafeRelease(mOffscreenTexture); + SafeRelease(mOffscreenRTView); + SafeRelease(mOffscreenSRView); + SafeRelease(mDepthStencilTexture); + SafeRelease(mDepthStencilDSView); +} + +EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight) +{ + ID3D11Device *device = mRenderer->getDevice(); + + ASSERT(device != NULL); + + // D3D11 does not allow zero size textures + ASSERT(backbufferWidth >= 1); + ASSERT(backbufferHeight >= 1); + + // Preserve the render target content + ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; + if (previousOffscreenTexture) + { + previousOffscreenTexture->AddRef(); + } + const int previousWidth = mWidth; + const int previousHeight = mHeight; + + releaseOffscreenTexture(); + + // If the app passed in a share handle, open the resource + // See EGL_ANGLE_d3d_share_handle_client_buffer + if (mAppCreatedShareHandle) + { + ID3D11Resource *tempResource11; + HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11); + + if (FAILED(result)) + { + ERR("Failed to open the swap chain pbuffer share handle: %08lX", result); + release(); + return EGL_BAD_PARAMETER; + } + + result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture); + tempResource11->Release(); + + if (FAILED(result)) + { + ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result); + release(); + return EGL_BAD_PARAMETER; + } + + // Validate offscreen texture parameters + D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; + mOffscreenTexture->GetDesc(&offscreenTextureDesc); + + if (offscreenTextureDesc.Width != (UINT)backbufferWidth + || offscreenTextureDesc.Height != (UINT)backbufferHeight + || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat) + || offscreenTextureDesc.MipLevels != 1 + || offscreenTextureDesc.ArraySize != 1) + { + ERR("Invalid texture parameters in the shared offscreen texture pbuffer"); + release(); + return EGL_BAD_PARAMETER; + } + } + else + { + const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport(); + + D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; + offscreenTextureDesc.Width = backbufferWidth; + offscreenTextureDesc.Height = backbufferHeight; + offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); + offscreenTextureDesc.MipLevels = 1; + offscreenTextureDesc.ArraySize = 1; + offscreenTextureDesc.SampleDesc.Count = 1; + offscreenTextureDesc.SampleDesc.Quality = 0; + offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT; + offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; + offscreenTextureDesc.CPUAccessFlags = 0; + offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0; + + HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture); + + if (FAILED(result)) + { + ERR("Could not create offscreen texture: %08lX", result); + release(); + + if (d3d11::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + + d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture"); + + // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client + if (useSharedResource) + { + IDXGIResource *offscreenTextureResource = NULL; + result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource); + + // Fall back to no share handle on failure + if (FAILED(result)) + { + ERR("Could not query offscreen texture resource: %08lX", result); + } + else + { + result = offscreenTextureResource->GetSharedHandle(&mShareHandle); + offscreenTextureResource->Release(); + + if (FAILED(result)) + { + mShareHandle = NULL; + ERR("Could not get offscreen texture shared handle: %08lX", result); + } + } + } + } + + HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView); + + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target"); + + result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource"); + + if (mDepthBufferFormat != GL_NONE) + { + D3D11_TEXTURE2D_DESC depthStencilDesc = {0}; + depthStencilDesc.Width = backbufferWidth; + depthStencilDesc.Height = backbufferHeight; + depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat); + depthStencilDesc.MipLevels = 1; + depthStencilDesc.ArraySize = 1; + depthStencilDesc.SampleDesc.Count = 1; + depthStencilDesc.SampleDesc.Quality = 0; + depthStencilDesc.Usage = D3D11_USAGE_DEFAULT; + depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + depthStencilDesc.CPUAccessFlags = 0; + depthStencilDesc.MiscFlags = 0; + + result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture); + if (FAILED(result)) + { + ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); + release(); + + if (d3d11::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture"); + + result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view"); + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + + if (previousOffscreenTexture != NULL) + { + D3D11_BOX sourceBox = {0}; + sourceBox.left = 0; + sourceBox.right = std::min(previousWidth, mWidth); + sourceBox.top = std::max(previousHeight - mHeight, 0); + sourceBox.bottom = previousHeight; + sourceBox.front = 0; + sourceBox.back = 1; + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + const int yoffset = std::max(mHeight - previousHeight, 0); + deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox); + + previousOffscreenTexture->Release(); + + if (mSwapChain) + { + swapRect(0, 0, mWidth, mHeight); + } + } + + return EGL_SUCCESS; +} + +EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) +{ + ID3D11Device *device = mRenderer->getDevice(); + + if (device == NULL) + { + return EGL_BAD_ACCESS; + } + + // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains + if (backbufferWidth < 1 || backbufferHeight < 1) + { + return EGL_SUCCESS; + } + + // Can only call resize if we have already created our swap buffer and resources + ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); + + SafeRelease(mBackBufferTexture); + SafeRelease(mBackBufferRTView); + + // Resize swap chain + DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); + HRESULT result = mSwapChain->ResizeBuffers(2, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0); + + if (FAILED(result)) + { + ERR("Error resizing swap chain buffers: 0x%08X", result); + release(); + + if (d3d11::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); + ASSERT(SUCCEEDED(result)); + if (SUCCEEDED(result)) + { + d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); + } + + result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); + ASSERT(SUCCEEDED(result)); + if (SUCCEEDED(result)) + { + d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); + } + + return resetOffscreenTexture(backbufferWidth, backbufferHeight); +} + +EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) +{ + ID3D11Device *device = mRenderer->getDevice(); + + if (device == NULL) + { + return EGL_BAD_ACCESS; + } + + // Release specific resources to free up memory for the new render target, while the + // old render target still exists for the purpose of preserving its contents. + SafeRelease(mSwapChain); + SafeRelease(mBackBufferTexture); + SafeRelease(mBackBufferRTView); + + mSwapInterval = static_cast(swapInterval); + if (mSwapInterval > 4) + { + // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range + return EGL_BAD_PARAMETER; + } + + // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains + if (backbufferWidth < 1 || backbufferHeight < 1) + { + releaseOffscreenTexture(); + return EGL_SUCCESS; + } + + if (mWindow) + { +#if !defined(ANGLE_OS_WINRT) + IDXGIFactory *factory = mRenderer->getDxgiFactory(); + + DXGI_SWAP_CHAIN_DESC swapChainDesc = {0}; + swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); + swapChainDesc.BufferDesc.Width = backbufferWidth; + swapChainDesc.BufferDesc.Height = backbufferHeight; + swapChainDesc.BufferCount = 2; + swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; + swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; + swapChainDesc.Windowed = TRUE; + swapChainDesc.OutputWindow = mWindow; +#else + IDXGIFactory2 *factory; + HRESULT result = mRenderer->getDxgiFactory()->QueryInterface(IID_PPV_ARGS(&factory)); + ASSERT(SUCCEEDED(result)); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; + swapChainDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); + swapChainDesc.Width = backbufferWidth; + swapChainDesc.Height = backbufferHeight; + swapChainDesc.Stereo = FALSE; +#if !defined(ANGLE_OS_WINPHONE) + swapChainDesc.BufferCount = 2; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; +#else + swapChainDesc.BufferCount = 1; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; +#endif +#endif + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.Flags = 0; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + +#if !defined(ANGLE_OS_WINRT) + HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); +#else + IDXGISwapChain1 *swapChain; + result = factory->CreateSwapChainForCoreWindow(device, mWindow, &swapChainDesc, NULL, &swapChain); + mSwapChain = swapChain; +#endif + + if (FAILED(result)) + { + ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); + release(); + + if (d3d11::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } +#if !defined(ANGLE_OS_WINRT) + else + { + // We cannot create a swap chain for an HWND that is owned by a different process on some versions of + // windows + DWORD currentProcessId = GetCurrentProcessId(); + DWORD wndProcessId; + GetWindowThreadProcessId(mWindow, &wndProcessId); + + if (currentProcessId != wndProcessId) + { + ERR("Could not create swap chain, window owned by different process"); + return EGL_BAD_NATIVE_WINDOW; + } + else + { + return EGL_BAD_ALLOC; + } + } +#else + return EGL_BAD_ALLOC; +#endif + } + + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); + + result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); + } + + // If we are resizing the swap chain, we don't wish to recreate all the static resources + if (!mPassThroughResourcesInit) + { + mPassThroughResourcesInit = true; + initPassThroughResources(); + } + + return resetOffscreenTexture(backbufferWidth, backbufferHeight); +} + +void SwapChain11::initPassThroughResources() +{ + ID3D11Device *device = mRenderer->getDevice(); + + ASSERT(device != NULL); + + // Make sure our resources are all not allocated, when we create + ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL); + ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL); + + D3D11_BUFFER_DESC vbDesc; + vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; + vbDesc.Usage = D3D11_USAGE_DYNAMIC; + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vbDesc.MiscFlags = 0; + vbDesc.StructureByteStride = 0; + + HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer"); + + D3D11_SAMPLER_DESC samplerDesc; + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.MipLODBias = 0.0f; + samplerDesc.MaxAnisotropy = 0; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + samplerDesc.BorderColor[0] = 0.0f; + samplerDesc.BorderColor[1] = 0.0f; + samplerDesc.BorderColor[2] = 0.0f; + samplerDesc.BorderColor[3] = 0.0f; + samplerDesc.MinLOD = 0; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + + result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler"); + + D3D11_INPUT_ELEMENT_DESC quadLayout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mPassThroughIL); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout"); + + result = device->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mPassThroughVS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader"); + + result = device->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mPassThroughPS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader"); +} + +// parameters should be validated/clamped by caller +EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +{ + if (!mSwapChain) + { + return EGL_SUCCESS; + } + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return EGL_BAD_ACCESS; + } + + d3d11::PositionTexCoordVertex *vertices = static_cast(mappedResource.pData); + + // Create a quad in homogeneous coordinates + float x1 = (x / float(mWidth)) * 2.0f - 1.0f; + float y1 = (y / float(mHeight)) * 2.0f - 1.0f; + float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; + float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; + + float u1 = x / float(mWidth); + float v1 = y / float(mHeight); + float u2 = (x + width) / float(mWidth); + float v2 = (y + height) / float(mHeight); + + d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1); + d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); + d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); + d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); + + deviceContext->Unmap(mQuadVB, 0); + + static UINT stride = sizeof(d3d11::PositionTexCoordVertex); + static UINT startIdx = 0; + deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx); + + // Apply state + deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); + + static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); + + deviceContext->RSSetState(NULL); + + // Apply shaders + deviceContext->IASetInputLayout(mPassThroughIL); + deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + deviceContext->VSSetShader(mPassThroughVS, NULL, 0); + deviceContext->PSSetShader(mPassThroughPS, NULL, 0); + deviceContext->GSSetShader(NULL, NULL, 0); + + // Apply render targets + mRenderer->setOneTimeRenderTarget(mBackBufferRTView); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = mWidth; + viewport.Height = mHeight; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + // Apply textures + deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView); + deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); + + // Draw + deviceContext->Draw(4, 0); + +#if ANGLE_FORCE_VSYNC_OFF + result = mSwapChain->Present(0, 0); +#else + result = mSwapChain->Present(mSwapInterval, 0); +#endif + + if (result == DXGI_ERROR_DEVICE_REMOVED) + { + HRESULT removedReason = device->GetDeviceRemovedReason(); + ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason); + return EGL_CONTEXT_LOST; + } + else if (result == DXGI_ERROR_DEVICE_RESET) + { + ERR("Present failed: the D3D11 device was reset from a bad command."); + return EGL_CONTEXT_LOST; + } + else if (FAILED(result)) + { + ERR("Present failed with error code 0x%08X", result); + } + + // Unbind + static ID3D11ShaderResourceView *const nullSRV = NULL; + deviceContext->PSSetShaderResources(0, 1, &nullSRV); + + mRenderer->unapplyRenderTargets(); + mRenderer->markAllStateDirty(); + + return EGL_SUCCESS; +} + +// Increments refcount on texture. +// caller must Release() the returned texture +ID3D11Texture2D *SwapChain11::getOffscreenTexture() +{ + if (mOffscreenTexture) + { + mOffscreenTexture->AddRef(); + } + + return mOffscreenTexture; +} + +// Increments refcount on view. +// caller must Release() the returned view +ID3D11RenderTargetView *SwapChain11::getRenderTarget() +{ + if (mOffscreenRTView) + { + mOffscreenRTView->AddRef(); + } + + return mOffscreenRTView; +} + +// Increments refcount on view. +// caller must Release() the returned view +ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource() +{ + if (mOffscreenSRView) + { + mOffscreenSRView->AddRef(); + } + + return mOffscreenSRView; +} + +// Increments refcount on view. +// caller must Release() the returned view +ID3D11DepthStencilView *SwapChain11::getDepthStencil() +{ + if (mDepthStencilDSView) + { + mDepthStencilDSView->AddRef(); + } + + return mDepthStencilDSView; +} + +ID3D11Texture2D *SwapChain11::getDepthStencilTexture() +{ + if (mDepthStencilTexture) + { + mDepthStencilTexture->AddRef(); + } + + return mDepthStencilTexture; +} + +SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain)); + return static_cast(swapChain); +} + +void SwapChain11::recreate() +{ + // possibly should use this method instead of reset +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h new file mode 100644 index 0000000000..2a030c839d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h @@ -0,0 +1,78 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChain11.h: Defines a back-end specific class for the D3D11 swap chain. + +#ifndef LIBGLESV2_RENDERER_SWAPCHAIN11_H_ +#define LIBGLESV2_RENDERER_SWAPCHAIN11_H_ + +#include "common/angleutils.h" +#include "libGLESv2/renderer/SwapChain.h" + +namespace rx +{ +class Renderer11; + +class SwapChain11 : public SwapChain +{ + public: + SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle, + GLenum backBufferFormat, GLenum depthBufferFormat); + virtual ~SwapChain11(); + + EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); + virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); + virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); + virtual void recreate(); + + virtual ID3D11Texture2D *getOffscreenTexture(); + virtual ID3D11RenderTargetView *getRenderTarget(); + virtual ID3D11ShaderResourceView *getRenderTargetShaderResource(); + + virtual ID3D11Texture2D *getDepthStencilTexture(); + virtual ID3D11DepthStencilView *getDepthStencil(); + + EGLint getWidth() const { return mWidth; } + EGLint getHeight() const { return mHeight; } + + static SwapChain11 *makeSwapChain11(SwapChain *swapChain); + + private: + DISALLOW_COPY_AND_ASSIGN(SwapChain11); + + void release(); + void initPassThroughResources(); + void releaseOffscreenTexture(); + EGLint resetOffscreenTexture(int backbufferWidth, int backbufferHeight); + + Renderer11 *mRenderer; + EGLint mHeight; + EGLint mWidth; + bool mAppCreatedShareHandle; + unsigned int mSwapInterval; + bool mPassThroughResourcesInit; + + IDXGISwapChain *mSwapChain; + + ID3D11Texture2D *mBackBufferTexture; + ID3D11RenderTargetView *mBackBufferRTView; + + ID3D11Texture2D *mOffscreenTexture; + ID3D11RenderTargetView *mOffscreenRTView; + ID3D11ShaderResourceView *mOffscreenSRView; + + ID3D11Texture2D *mDepthStencilTexture; + ID3D11DepthStencilView *mDepthStencilDSView; + + ID3D11Buffer *mQuadVB; + ID3D11SamplerState *mPassThroughSampler; + ID3D11InputLayout *mPassThroughIL; + ID3D11VertexShader *mPassThroughVS; + ID3D11PixelShader *mPassThroughPS; +}; + +} +#endif // LIBGLESV2_RENDERER_SWAPCHAIN11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp new file mode 100644 index 0000000000..fdfbe526ec --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp @@ -0,0 +1,667 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived +// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. + +#include "libGLESv2/renderer/d3d11/TextureStorage11.h" + +#include "libGLESv2/renderer/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d11/RenderTarget11.h" +#include "libGLESv2/renderer/d3d11/SwapChain11.h" +#include "libGLESv2/renderer/d3d11/renderer11_utils.h" + +#include "libGLESv2/utilities.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags) + : mBindFlags(bindFlags), + mLodOffset(0), + mMipLevels(0), + mTexture(NULL), + mTextureFormat(DXGI_FORMAT_UNKNOWN), + mShaderResourceFormat(DXGI_FORMAT_UNKNOWN), + mRenderTargetFormat(DXGI_FORMAT_UNKNOWN), + mDepthStencilFormat(DXGI_FORMAT_UNKNOWN), + mSRV(NULL), + mTextureWidth(0), + mTextureHeight(0) +{ + mRenderer = Renderer11::makeRenderer11(renderer); +} + +TextureStorage11::~TextureStorage11() +{ +} + +TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage)); + return static_cast(storage); +} + +DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable) +{ + UINT bindFlags = D3D11_BIND_SHADER_RESOURCE; + + if (d3d11::IsDepthStencilFormat(format)) + { + bindFlags |= D3D11_BIND_DEPTH_STENCIL; + } + else if(forceRenderable || (TextureStorage11::IsTextureFormatRenderable(format) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE))) + { + bindFlags |= D3D11_BIND_RENDER_TARGET; + } + return bindFlags; +} + +bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format) +{ + switch(format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_A8_UNORM: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_R16G16_FLOAT: + return true; + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_R32G32B32_FLOAT: // not renderable on all devices + return false; + default: + UNREACHABLE(); + return false; + } +} + +UINT TextureStorage11::getBindFlags() const +{ + return mBindFlags; +} + +ID3D11Texture2D *TextureStorage11::getBaseTexture() const +{ + return mTexture; +} + +int TextureStorage11::getLodOffset() const +{ + return mLodOffset; +} + +bool TextureStorage11::isRenderTarget() const +{ + return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0; +} + +bool TextureStorage11::isManaged() const +{ + return false; +} + +int TextureStorage11::levelCount() +{ + int levels = 0; + if (getBaseTexture()) + { + levels = mMipLevels - getLodOffset(); + } + return levels; +} + +UINT TextureStorage11::getSubresourceIndex(int level, int faceIndex) +{ + UINT index = 0; + if (getBaseTexture()) + { + index = D3D11CalcSubresource(level, faceIndex, mMipLevels); + } + return index; +} + +bool TextureStorage11::updateSubresourceLevel(ID3D11Texture2D *srcTexture, unsigned int sourceSubresource, + int level, int face, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height) +{ + if (srcTexture) + { + // Round up the width and height to the nearest multiple of dimension alignment + unsigned int dimensionAlignment = d3d11::GetTextureFormatDimensionAlignment(mTextureFormat); + width = width + dimensionAlignment - 1 - (width - 1) % dimensionAlignment; + height = height + dimensionAlignment - 1 - (height - 1) % dimensionAlignment; + + D3D11_BOX srcBox; + srcBox.left = xoffset; + srcBox.top = yoffset; + srcBox.right = xoffset + width; + srcBox.bottom = yoffset + height; + srcBox.front = 0; + srcBox.back = 1; + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + ASSERT(getBaseTexture()); + context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level + mLodOffset, face), + xoffset, yoffset, 0, srcTexture, sourceSubresource, &srcBox); + return true; + } + + return false; +} + +void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest) +{ + if (source && dest) + { + ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView(); + ID3D11RenderTargetView *destRTV = dest->getRenderTargetView(); + + if (sourceSRV && destRTV) + { + gl::Rectangle sourceArea; + sourceArea.x = 0; + sourceArea.y = 0; + sourceArea.width = source->getWidth(); + sourceArea.height = source->getHeight(); + + gl::Rectangle destArea; + destArea.x = 0; + destArea.y = 0; + destArea.width = dest->getWidth(); + destArea.height = dest->getHeight(); + + mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(), + destRTV, destArea, dest->getWidth(), dest->getHeight(), + GL_RGBA); + } + } +} + +TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain) + : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE) +{ + mTexture = swapchain->getOffscreenTexture(); + mSRV = swapchain->getRenderTargetShaderResource(); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mRenderTarget[i] = NULL; + } + + D3D11_TEXTURE2D_DESC texDesc; + mTexture->GetDesc(&texDesc); + mMipLevels = texDesc.MipLevels; + mTextureFormat = texDesc.Format; + mTextureWidth = texDesc.Width; + mTextureHeight = texDesc.Height; + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + mSRV->GetDesc(&srvDesc); + mShaderResourceFormat = srvDesc.Format; + + ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget(); + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + offscreenRTV->GetDesc(&rtvDesc); + mRenderTargetFormat = rtvDesc.Format; + offscreenRTV->Release(); + + mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; +} + +TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) + : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()), usage, forceRenderable)) +{ + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mRenderTarget[i] = NULL; + } + + DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel()); + if (d3d11::IsDepthStencilFormat(convertedFormat)) + { + mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); + mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat); + mDepthStencilFormat = convertedFormat; + mRenderTargetFormat = DXGI_FORMAT_UNKNOWN; + } + else + { + mTextureFormat = convertedFormat; + mShaderResourceFormat = convertedFormat; + mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; + mRenderTargetFormat = convertedFormat; + } + + // if the width or height is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (width > 0 && height > 0) + { + // adjust size if needed for compressed textures + gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; // Compressed texture size constraints? + desc.Height = height; + desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0; + desc.ArraySize = 1; + desc.Format = mTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + gl::error(GL_OUT_OF_MEMORY); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + gl::error(GL_OUT_OF_MEMORY); + } + else + { + mTexture->GetDesc(&desc); + mMipLevels = desc.MipLevels; + mTextureWidth = desc.Width; + mTextureHeight = desc.Height; + } + } +} + +TextureStorage11_2D::~TextureStorage11_2D() +{ + if (mTexture) + { + mTexture->Release(); + mTexture = NULL; + } + + if (mSRV) + { + mSRV->Release(); + mSRV = NULL; + } + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + delete mRenderTarget[i]; + mRenderTarget[i] = NULL; + } +} + +TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage)); + return static_cast(storage); +} + +RenderTarget *TextureStorage11_2D::getRenderTarget(int level) +{ + if (level >= 0 && level < static_cast(mMipLevels)) + { + if (!mRenderTarget[level]) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = mShaderResourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MostDetailedMip = level; + srvDesc.Texture2D.MipLevels = level ? 1 : -1; + + ID3D11ShaderResourceView *srv; + result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = level; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + srv->Release(); + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 + // also needs to keep a reference to the texture. + mTexture->AddRef(); + + mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, + std::max(mTextureWidth >> level, 1U), + std::max(mTextureHeight >> level, 1U)); + } + else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mDepthStencilFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + dsvDesc.Texture2D.MipSlice = level; + dsvDesc.Flags = 0; + + ID3D11DepthStencilView *dsv; + result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); + + if (result == E_OUTOFMEMORY) + { + srv->Release(); + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 + // also needs to keep a reference to the texture. + mTexture->AddRef(); + + mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, + std::max(mTextureWidth >> level, 1U), + std::max(mTextureHeight >> level, 1U)); + } + else + { + UNREACHABLE(); + } + } + + return mRenderTarget[level]; + } + else + { + return NULL; + } +} + +ID3D11ShaderResourceView *TextureStorage11_2D::getSRV() +{ + if (!mSRV) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = mShaderResourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels); + srvDesc.Texture2D.MostDetailedMip = 0; + + HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSRV; +} + +void TextureStorage11_2D::generateMipmap(int level) +{ + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level)); + + generateMipmapLayer(source, dest); +} + +TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) + : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()), usage, forceRenderable)) +{ + for (unsigned int i = 0; i < 6; i++) + { + for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++) + { + mRenderTarget[i][j] = NULL; + } + } + + DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel()); + if (d3d11::IsDepthStencilFormat(convertedFormat)) + { + mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); + mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat); + mDepthStencilFormat = convertedFormat; + mRenderTargetFormat = DXGI_FORMAT_UNKNOWN; + } + else + { + mTextureFormat = convertedFormat; + mShaderResourceFormat = convertedFormat; + mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; + mRenderTargetFormat = convertedFormat; + } + + // if the size is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (size > 0) + { + // adjust size if needed for compressed textures + int height = size; + gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = size; + desc.Height = size; + desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0; + desc.ArraySize = 6; + desc.Format = mTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + gl::error(GL_OUT_OF_MEMORY); + } + else + { + mTexture->GetDesc(&desc); + mMipLevels = desc.MipLevels; + mTextureWidth = desc.Width; + mTextureHeight = desc.Height; + } + } +} + +TextureStorage11_Cube::~TextureStorage11_Cube() +{ + if (mTexture) + { + mTexture->Release(); + mTexture = NULL; + } + + if (mSRV) + { + mSRV->Release(); + mSRV = NULL; + } + + for (unsigned int i = 0; i < 6; i++) + { + for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++) + { + delete mRenderTarget[i][j]; + mRenderTarget[i][j] = NULL; + } + } +} + +TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage)); + return static_cast(storage); +} + +RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level) +{ + unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget); + if (level >= 0 && level < static_cast(mMipLevels)) + { + if (!mRenderTarget[faceIdx][level]) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = mShaderResourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube + srvDesc.Texture2DArray.MostDetailedMip = level; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = faceIdx; + srvDesc.Texture2DArray.ArraySize = 1; + + ID3D11ShaderResourceView *srv; + result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = level; + rtvDesc.Texture2DArray.FirstArraySlice = faceIdx; + rtvDesc.Texture2DArray.ArraySize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + srv->Release(); + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 + // also needs to keep a reference to the texture. + mTexture->AddRef(); + + mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, + std::max(mTextureWidth >> level, 1U), + std::max(mTextureHeight >> level, 1U)); + } + else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mRenderTargetFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; + dsvDesc.Texture2DArray.MipSlice = level; + dsvDesc.Texture2DArray.FirstArraySlice = faceIdx; + dsvDesc.Texture2DArray.ArraySize = 1; + + ID3D11DepthStencilView *dsv; + result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); + + if (result == E_OUTOFMEMORY) + { + srv->Release(); + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 + // also needs to keep a reference to the texture. + mTexture->AddRef(); + + mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, + std::max(mTextureWidth >> level, 1U), + std::max(mTextureHeight >> level, 1U)); + } + else + { + UNREACHABLE(); + } + } + + return mRenderTarget[faceIdx][level]; + } + else + { + return NULL; + } +} + +ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV() +{ + if (!mSRV) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = mShaderResourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels); + srvDesc.TextureCube.MostDetailedMip = 0; + + HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSRV; +} + +void TextureStorage11_Cube::generateMipmap(int face, int level) +{ + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level)); + + generateMipmapLayer(source, dest); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h new file mode 100644 index 0000000000..3c5ded05b8 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h @@ -0,0 +1,120 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureStorage11.h: Defines the abstract rx::TextureStorage11 class and its concrete derived +// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. + +#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ +#define LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ + +#include "libGLESv2/Texture.h" +#include "libGLESv2/renderer/TextureStorage.h" + +namespace rx +{ +class RenderTarget; +class RenderTarget11; +class Renderer; +class Renderer11; +class SwapChain11; + +class TextureStorage11 : public TextureStorage +{ + public: + TextureStorage11(Renderer *renderer, UINT bindFlags); + virtual ~TextureStorage11(); + + static TextureStorage11 *makeTextureStorage11(TextureStorage *storage); + + static DWORD GetTextureBindFlags(DXGI_FORMAT d3dfmt, GLenum glusage, bool forceRenderable); + static bool IsTextureFormatRenderable(DXGI_FORMAT format); + + UINT getBindFlags() const; + + virtual ID3D11Texture2D *getBaseTexture() const; + virtual ID3D11ShaderResourceView *getSRV() = 0; + virtual RenderTarget *getRenderTarget() { return getRenderTarget(0); } + virtual RenderTarget *getRenderTarget(int level) { return NULL; } + virtual RenderTarget *getRenderTarget(GLenum faceTarget) { return getRenderTarget(faceTarget, 0); } + virtual RenderTarget *getRenderTarget(GLenum faceTarget, int level) { return NULL; } + + virtual void generateMipmap(int level) {}; + virtual void generateMipmap(int face, int level) {}; + + virtual int getLodOffset() const; + virtual bool isRenderTarget() const; + virtual bool isManaged() const; + virtual int levelCount(); + UINT getSubresourceIndex(int level, int faceTarget); + + bool updateSubresourceLevel(ID3D11Texture2D *texture, unsigned int sourceSubresource, int level, + int faceTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + + protected: + void generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest); + + Renderer11 *mRenderer; + int mLodOffset; + unsigned int mMipLevels; + + ID3D11Texture2D *mTexture; + DXGI_FORMAT mTextureFormat; + DXGI_FORMAT mShaderResourceFormat; + DXGI_FORMAT mRenderTargetFormat; + DXGI_FORMAT mDepthStencilFormat; + unsigned int mTextureWidth; + unsigned int mTextureHeight; + + ID3D11ShaderResourceView *mSRV; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage11); + + const UINT mBindFlags; +}; + +class TextureStorage11_2D : public TextureStorage11 +{ + public: + TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain); + TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); + virtual ~TextureStorage11_2D(); + + static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage); + + virtual ID3D11ShaderResourceView *getSRV(); + virtual RenderTarget *getRenderTarget(int level); + + virtual void generateMipmap(int level); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D); + + RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureStorage11_Cube : public TextureStorage11 +{ + public: + TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); + virtual ~TextureStorage11_Cube(); + + static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage); + + virtual ID3D11ShaderResourceView *getSRV(); + virtual RenderTarget *getRenderTarget(GLenum faceTarget, int level); + + virtual void generateMipmap(int face, int level); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube); + + RenderTarget11 *mRenderTarget[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +} + +#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp new file mode 100644 index 0000000000..6f9b4181f1 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp @@ -0,0 +1,440 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation. + +#include "libGLESv2/renderer/d3d11/VertexBuffer11.h" +#include "libGLESv2/renderer/BufferStorage.h" + +#include "libGLESv2/Buffer.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" +#include "libGLESv2/Context.h" + +namespace rx +{ + +VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer) +{ + mBuffer = NULL; + mBufferSize = 0; + mDynamicUsage = false; +} + +VertexBuffer11::~VertexBuffer11() +{ + if (mBuffer) + { + mBuffer->Release(); + mBuffer = NULL; + } +} + +bool VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) +{ + if (mBuffer) + { + mBuffer->Release(); + mBuffer = NULL; + } + + updateSerial(); + + if (size > 0) + { + ID3D11Device* dxDevice = mRenderer->getDevice(); + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = size; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); + if (FAILED(result)) + { + return false; + } + } + + mBufferSize = size; + mDynamicUsage = dynamicUsage; + return true; +} + +VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer)); + return static_cast(vetexBuffer); +} + +bool VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, + GLsizei instances, unsigned int offset) +{ + if (mBuffer) + { + gl::Buffer *buffer = attrib.mBoundBuffer.get(); + + int inputStride = attrib.stride(); + const VertexConverter &converter = getVertexConversion(attrib); + + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Vertex buffer map failed with error 0x%08x", result); + return false; + } + + char* output = reinterpret_cast(mappedResource.pData) + offset; + + const char *input = NULL; + if (buffer) + { + BufferStorage *storage = buffer->getStorage(); + input = static_cast(storage->getData()) + static_cast(attrib.mOffset); + } + else + { + input = static_cast(attrib.mPointer); + } + + if (instances == 0 || attrib.mDivisor == 0) + { + input += inputStride * start; + } + + converter.conversionFunc(input, inputStride, count, output); + + dxContext->Unmap(mBuffer, 0); + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +bool VertexBuffer11::storeRawData(const void* data, unsigned int size, unsigned int offset) +{ + if (mBuffer) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Vertex buffer map failed with error 0x%08x", result); + return false; + } + + char* bufferData = static_cast(mappedResource.pData); + memcpy(bufferData + offset, data, size); + + dxContext->Unmap(mBuffer, 0); + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +bool VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, + GLsizei instances, unsigned int *outSpaceRequired) const +{ + unsigned int elementSize = getVertexConversion(attrib).outputElementSize; + + unsigned int elementCount = 0; + if (instances == 0 || attrib.mDivisor == 0) + { + elementCount = count; + } + else + { + if (static_cast(instances) < std::numeric_limits::max() - (attrib.mDivisor - 1)) + { + // Round up + elementCount = (static_cast(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor; + } + else + { + elementCount = instances / attrib.mDivisor; + } + } + + if (elementSize <= std::numeric_limits::max() / elementCount) + { + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * elementCount; + } + return true; + } + else + { + return false; + } +} + +bool VertexBuffer11::requiresConversion(const gl::VertexAttribute &attrib) const +{ + return !getVertexConversion(attrib).identity; +} + +unsigned int VertexBuffer11::getBufferSize() const +{ + return mBufferSize; +} + +bool VertexBuffer11::setBufferSize(unsigned int size) +{ + if (size > mBufferSize) + { + return initialize(size, mDynamicUsage); + } + else + { + return true; + } +} + +bool VertexBuffer11::discard() +{ + if (mBuffer) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Vertex buffer map failed with error 0x%08x", result); + return false; + } + + dxContext->Unmap(mBuffer, 0); + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +unsigned int VertexBuffer11::getVertexSize(const gl::VertexAttribute &attrib) const +{ + return getVertexConversion(attrib).outputElementSize; +} + +DXGI_FORMAT VertexBuffer11::getDXGIFormat(const gl::VertexAttribute &attrib) const +{ + return getVertexConversion(attrib).dxgiFormat; +} + +ID3D11Buffer *VertexBuffer11::getBuffer() const +{ + return mBuffer; +} + +template +static void copyVertexData(const void *input, unsigned int stride, unsigned int count, void *output) +{ + unsigned int attribSize = sizeof(T) * componentCount; + + if (attribSize == stride && !widen) + { + memcpy(output, input, count * attribSize); + } + else + { + unsigned int outputStride = widen ? 4 : componentCount; + T defaultVal = normalized ? std::numeric_limits::max() : T(1); + + for (unsigned int i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast(reinterpret_cast(input) + i * stride); + T *offsetOutput = reinterpret_cast(output) + i * outputStride; + + for (unsigned int j = 0; j < componentCount; j++) + { + offsetOutput[j] = offsetInput[j]; + } + + if (widen) + { + offsetOutput[3] = defaultVal; + } + } + } +} + +template +static void copyFixedVertexData(const void* input, unsigned int stride, unsigned int count, void* output) +{ + static const float divisor = 1.0f / (1 << 16); + + for (unsigned int i = 0; i < count; i++) + { + const GLfixed* offsetInput = reinterpret_cast(reinterpret_cast(input) + stride * i); + float* offsetOutput = reinterpret_cast(output) + i * componentCount; + + for (unsigned int j = 0; j < componentCount; j++) + { + offsetOutput[j] = static_cast(offsetInput[j]) * divisor; + } + } +} + +template +static void copyToFloatVertexData(const void* input, unsigned int stride, unsigned int count, void* output) +{ + typedef std::numeric_limits NL; + + for (unsigned int i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast(reinterpret_cast(input) + stride * i); + float *offsetOutput = reinterpret_cast(output) + i * componentCount; + + for (unsigned int j = 0; j < componentCount; j++) + { + if (normalized) + { + if (NL::is_signed) + { + const float divisor = 1.0f / (2 * static_cast(NL::max()) + 1); + offsetOutput[j] = (2 * static_cast(offsetInput[j]) + 1) * divisor; + } + else + { + offsetOutput[j] = static_cast(offsetInput[j]) / NL::max(); + } + } + else + { + offsetOutput[j] = static_cast(offsetInput[j]); + } + } + } +} + +const VertexBuffer11::VertexConverter VertexBuffer11::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = +{ + { // GL_BYTE + { // unnormalized + { ©ToFloatVertexData, false, DXGI_FORMAT_R32_FLOAT, 4 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, + }, + { // normalized + { ©VertexData, true, DXGI_FORMAT_R8_SNORM, 1 }, + { ©VertexData, true, DXGI_FORMAT_R8G8_SNORM, 2 }, + { ©VertexData, false, DXGI_FORMAT_R8G8B8A8_SNORM, 4 }, + { ©VertexData, true, DXGI_FORMAT_R8G8B8A8_SNORM, 4 }, + }, + }, + { // GL_UNSIGNED_BYTE + { // unnormalized + { ©ToFloatVertexData, false, DXGI_FORMAT_R32_FLOAT, 4 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, + }, + { // normalized + { ©VertexData, true, DXGI_FORMAT_R8_UNORM, 1 }, + { ©VertexData, true, DXGI_FORMAT_R8G8_UNORM, 2 }, + { ©VertexData, false, DXGI_FORMAT_R8G8B8A8_UNORM, 4 }, + { ©VertexData, true, DXGI_FORMAT_R8G8B8A8_UNORM, 4 }, + }, + }, + { // GL_SHORT + { // unnormalized + { ©ToFloatVertexData, false, DXGI_FORMAT_R32_FLOAT, 4 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, + }, + { // normalized + { ©VertexData, true, DXGI_FORMAT_R16_SNORM, 2 }, + { ©VertexData, true, DXGI_FORMAT_R16G16_SNORM, 4 }, + { ©VertexData, false, DXGI_FORMAT_R16G16B16A16_SNORM, 8 }, + { ©VertexData, true, DXGI_FORMAT_R16G16B16A16_SNORM, 8 }, + }, + }, + { // GL_UNSIGNED_SHORT + { // unnormalized + { ©ToFloatVertexData, false, DXGI_FORMAT_R32_FLOAT, 4 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, + { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, + }, + { // normalized + { ©VertexData, true, DXGI_FORMAT_R16_UNORM, 2 }, + { ©VertexData, true, DXGI_FORMAT_R16G16_UNORM, 4 }, + { ©VertexData, false, DXGI_FORMAT_R16G16B16A16_UNORM, 8 }, + { ©VertexData, true, DXGI_FORMAT_R16G16B16A16_UNORM, 8 }, + }, + }, + { // GL_FIXED + { // unnormalized + { ©FixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 }, + { ©FixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, + { ©FixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, + { ©FixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, + }, + { // normalized + { ©FixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 }, + { ©FixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, + { ©FixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, + { ©FixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, + }, + }, + { // GL_FLOAT + { // unnormalized + { ©VertexData, true, DXGI_FORMAT_R32_FLOAT, 4 }, + { ©VertexData, true, DXGI_FORMAT_R32G32_FLOAT, 8 }, + { ©VertexData, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, + { ©VertexData, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, + }, + { // normalized + { ©VertexData, true, DXGI_FORMAT_R32_FLOAT, 4 }, + { ©VertexData, true, DXGI_FORMAT_R32G32_FLOAT, 8 }, + { ©VertexData, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, + { ©VertexData, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, + }, + }, +}; + +const VertexBuffer11::VertexConverter &VertexBuffer11::getVertexConversion(const gl::VertexAttribute &attribute) +{ + unsigned int typeIndex = 0; + switch (attribute.mType) + { + case GL_BYTE: typeIndex = 0; break; + case GL_UNSIGNED_BYTE: typeIndex = 1; break; + case GL_SHORT: typeIndex = 2; break; + case GL_UNSIGNED_SHORT: typeIndex = 3; break; + case GL_FIXED: typeIndex = 4; break; + case GL_FLOAT: typeIndex = 5; break; + default: UNREACHABLE(); break; + } + + return mPossibleTranslations[typeIndex][attribute.mNormalized ? 1 : 0][attribute.mSize - 1]; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h new file mode 100644 index 0000000000..eceb426e82 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h @@ -0,0 +1,74 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexBuffer11.h: Defines the D3D11 VertexBuffer implementation. + +#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ +#define LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ + +#include "libGLESv2/renderer/VertexBuffer.h" + +namespace rx +{ +class Renderer11; + +class VertexBuffer11 : public VertexBuffer +{ + public: + explicit VertexBuffer11(rx::Renderer11 *const renderer); + virtual ~VertexBuffer11(); + + virtual bool initialize(unsigned int size, bool dynamicUsage); + + static VertexBuffer11 *makeVertexBuffer11(VertexBuffer *vetexBuffer); + + virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, + unsigned int offset); + virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset); + + virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, + unsigned int *outSpaceRequired) const; + + virtual bool requiresConversion(const gl::VertexAttribute &attrib) const; + + virtual unsigned int getBufferSize() const; + virtual bool setBufferSize(unsigned int size); + virtual bool discard(); + + unsigned int getVertexSize(const gl::VertexAttribute &attrib) const; + DXGI_FORMAT getDXGIFormat(const gl::VertexAttribute &attrib) const; + + ID3D11Buffer *getBuffer() const; + + private: + DISALLOW_COPY_AND_ASSIGN(VertexBuffer11); + + rx::Renderer11 *const mRenderer; + + ID3D11Buffer *mBuffer; + unsigned int mBufferSize; + bool mDynamicUsage; + + typedef void (*VertexConversionFunction)(const void *, unsigned int, unsigned int, void *); + struct VertexConverter + { + VertexConversionFunction conversionFunc; + bool identity; + DXGI_FORMAT dxgiFormat; + unsigned int outputElementSize; + }; + + enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; + + // This table is used to generate mAttributeTypes. + static const VertexConverter mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1] + + static const VertexConverter &getVertexConversion(const gl::VertexAttribute &attribute); +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp new file mode 100644 index 0000000000..34b8259a80 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp @@ -0,0 +1,688 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// renderer11_utils.cpp: Conversion functions and other utility routines +// specific to the D3D11 renderer. + +#include "libGLESv2/renderer/d3d11/renderer11_utils.h" + +#include "common/debug.h" + +namespace gl_d3d11 +{ + +D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha) +{ + D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO; + + switch (glBlend) + { + case GL_ZERO: d3dBlend = D3D11_BLEND_ZERO; break; + case GL_ONE: d3dBlend = D3D11_BLEND_ONE; break; + case GL_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR); break; + case GL_ONE_MINUS_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR); break; + case GL_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR); break; + case GL_ONE_MINUS_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR); break; + case GL_SRC_ALPHA: d3dBlend = D3D11_BLEND_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3D11_BLEND_INV_SRC_ALPHA; break; + case GL_DST_ALPHA: d3dBlend = D3D11_BLEND_DEST_ALPHA; break; + case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3D11_BLEND_INV_DEST_ALPHA; break; + case GL_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break; + case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break; + case GL_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break; + case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break; + case GL_SRC_ALPHA_SATURATE: d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT; break; + default: UNREACHABLE(); + } + + return d3dBlend; +} + +D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp) +{ + D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD; + + switch (glBlendOp) + { + case GL_FUNC_ADD: d3dBlendOp = D3D11_BLEND_OP_ADD; break; + case GL_FUNC_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_SUBTRACT; break; + case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT; break; + default: UNREACHABLE(); + } + + return d3dBlendOp; +} + +UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha) +{ + UINT8 mask = 0; + if (red) + { + mask |= D3D11_COLOR_WRITE_ENABLE_RED; + } + if (green) + { + mask |= D3D11_COLOR_WRITE_ENABLE_GREEN; + } + if (blue) + { + mask |= D3D11_COLOR_WRITE_ENABLE_BLUE; + } + if (alpha) + { + mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA; + } + return mask; +} + +D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode) +{ + D3D11_CULL_MODE cull = D3D11_CULL_NONE; + + if (cullEnabled) + { + switch (cullMode) + { + case GL_FRONT: cull = D3D11_CULL_FRONT; break; + case GL_BACK: cull = D3D11_CULL_BACK; break; + case GL_FRONT_AND_BACK: cull = D3D11_CULL_NONE; break; + default: UNREACHABLE(); + } + } + else + { + cull = D3D11_CULL_NONE; + } + + return cull; +} + +D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison) +{ + D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER; + switch (comparison) + { + case GL_NEVER: d3dComp = D3D11_COMPARISON_NEVER; break; + case GL_ALWAYS: d3dComp = D3D11_COMPARISON_ALWAYS; break; + case GL_LESS: d3dComp = D3D11_COMPARISON_LESS; break; + case GL_LEQUAL: d3dComp = D3D11_COMPARISON_LESS_EQUAL; break; + case GL_EQUAL: d3dComp = D3D11_COMPARISON_EQUAL; break; + case GL_GREATER: d3dComp = D3D11_COMPARISON_GREATER; break; + case GL_GEQUAL: d3dComp = D3D11_COMPARISON_GREATER_EQUAL; break; + case GL_NOTEQUAL: d3dComp = D3D11_COMPARISON_NOT_EQUAL; break; + default: UNREACHABLE(); + } + + return d3dComp; +} + +D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled) +{ + return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; +} + +UINT8 ConvertStencilMask(GLuint stencilmask) +{ + return static_cast(stencilmask); +} + +D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp) +{ + D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP; + + switch (stencilOp) + { + case GL_ZERO: d3dStencilOp = D3D11_STENCIL_OP_ZERO; break; + case GL_KEEP: d3dStencilOp = D3D11_STENCIL_OP_KEEP; break; + case GL_REPLACE: d3dStencilOp = D3D11_STENCIL_OP_REPLACE; break; + case GL_INCR: d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT; break; + case GL_DECR: d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT; break; + case GL_INVERT: d3dStencilOp = D3D11_STENCIL_OP_INVERT; break; + case GL_INCR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_INCR; break; + case GL_DECR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_DECR; break; + default: UNREACHABLE(); + } + + return d3dStencilOp; +} + +D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy) +{ + if (maxAnisotropy > 1.0f) + { + return D3D11_ENCODE_ANISOTROPIC_FILTER(false); + } + else + { + D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT; + D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT; + switch (minFilter) + { + case GL_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break; + case GL_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break; + case GL_NEAREST_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break; + case GL_LINEAR_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break; + case GL_NEAREST_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_LINEAR; break; + case GL_LINEAR_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_LINEAR; break; + default: UNREACHABLE(); + } + + D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT; + switch (magFilter) + { + case GL_NEAREST: dxMag = D3D11_FILTER_TYPE_POINT; break; + case GL_LINEAR: dxMag = D3D11_FILTER_TYPE_LINEAR; break; + default: UNREACHABLE(); + } + + return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip, false); + } +} + +D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap) +{ + switch (wrap) + { + case GL_REPEAT: return D3D11_TEXTURE_ADDRESS_WRAP; + case GL_CLAMP_TO_EDGE: return D3D11_TEXTURE_ADDRESS_CLAMP; + case GL_MIRRORED_REPEAT: return D3D11_TEXTURE_ADDRESS_MIRROR; + default: UNREACHABLE(); + } + + return D3D11_TEXTURE_ADDRESS_WRAP; +} + +FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset) +{ + return (minFilter == GL_NEAREST || minFilter == GL_LINEAR) ? static_cast(lodOffset) : -FLT_MAX; +} + +FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset) +{ + return (minFilter == GL_NEAREST || minFilter == GL_LINEAR) ? static_cast(lodOffset) : FLT_MAX; +} + +} + +namespace d3d11_gl +{ + +GLenum ConvertBackBufferFormat(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: return GL_RGBA8_OES; + case DXGI_FORMAT_B8G8R8A8_UNORM: return GL_BGRA8_EXT; + default: + UNREACHABLE(); + } + + return GL_RGBA8_OES; +} + +GLenum ConvertDepthStencilFormat(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_UNKNOWN: return GL_NONE; + case DXGI_FORMAT_D16_UNORM: return GL_DEPTH_COMPONENT16; + case DXGI_FORMAT_D24_UNORM_S8_UINT: return GL_DEPTH24_STENCIL8_OES; + default: + UNREACHABLE(); + } + + return GL_DEPTH24_STENCIL8_OES; +} + +GLenum ConvertRenderbufferFormat(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_B8G8R8A8_UNORM: + return GL_BGRA8_EXT; + case DXGI_FORMAT_R8G8B8A8_UNORM: + return GL_RGBA8_OES; + case DXGI_FORMAT_D16_UNORM: + return GL_DEPTH_COMPONENT16; + case DXGI_FORMAT_D24_UNORM_S8_UINT: + return GL_DEPTH24_STENCIL8_OES; + default: + UNREACHABLE(); + } + + return GL_RGBA8_OES; +} + +GLenum ConvertTextureInternalFormat(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + return GL_RGBA8_OES; + case DXGI_FORMAT_A8_UNORM: + return GL_ALPHA8_EXT; + case DXGI_FORMAT_BC1_UNORM: + return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + case DXGI_FORMAT_BC2_UNORM: + return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE; + case DXGI_FORMAT_BC3_UNORM: + return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE; + case DXGI_FORMAT_R32G32B32A32_FLOAT: + return GL_RGBA32F_EXT; + case DXGI_FORMAT_R32G32B32_FLOAT: + return GL_RGB32F_EXT; + case DXGI_FORMAT_R16G16B16A16_FLOAT: + return GL_RGBA16F_EXT; + case DXGI_FORMAT_B8G8R8A8_UNORM: + return GL_BGRA8_EXT; + case DXGI_FORMAT_R8_UNORM: + return GL_R8_EXT; + case DXGI_FORMAT_R8G8_UNORM: + return GL_RG8_EXT; + case DXGI_FORMAT_R16_FLOAT: + return GL_R16F_EXT; + case DXGI_FORMAT_R16G16_FLOAT: + return GL_RG16F_EXT; + case DXGI_FORMAT_D16_UNORM: + return GL_DEPTH_COMPONENT16; + case DXGI_FORMAT_D24_UNORM_S8_UINT: + return GL_DEPTH24_STENCIL8_OES; + case DXGI_FORMAT_UNKNOWN: + return GL_NONE; + default: + UNREACHABLE(); + } + + return GL_RGBA8_OES; +} + +} + +namespace gl_d3d11 +{ + +DXGI_FORMAT ConvertRenderbufferFormat(GLenum format) +{ + switch (format) + { + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8_OES: + case GL_RGB565: + case GL_RGB8_OES: + return DXGI_FORMAT_R8G8B8A8_UNORM; + case GL_BGRA8_EXT: + return DXGI_FORMAT_B8G8R8A8_UNORM; + case GL_DEPTH_COMPONENT16: + return DXGI_FORMAT_D16_UNORM; + case GL_STENCIL_INDEX8: + case GL_DEPTH24_STENCIL8_OES: + return DXGI_FORMAT_D24_UNORM_S8_UINT; + default: + UNREACHABLE(); + } + + return DXGI_FORMAT_R8G8B8A8_UNORM; +} + +DXGI_FORMAT ConvertTextureFormat(GLenum internalformat, D3D_FEATURE_LEVEL featureLevel) +{ + switch (internalformat) + { + case GL_RGB565: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGB8_OES: + case GL_RGBA8_OES: + case GL_LUMINANCE8_EXT: + case GL_LUMINANCE8_ALPHA8_EXT: + return DXGI_FORMAT_R8G8B8A8_UNORM; + case GL_ALPHA8_EXT: + return featureLevel >= D3D_FEATURE_LEVEL_10_0 ? DXGI_FORMAT_A8_UNORM : DXGI_FORMAT_B8G8R8A8_UNORM; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + return DXGI_FORMAT_BC1_UNORM; + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + return DXGI_FORMAT_BC2_UNORM; + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + return DXGI_FORMAT_BC3_UNORM; + case GL_RGBA32F_EXT: + case GL_ALPHA32F_EXT: + case GL_LUMINANCE_ALPHA32F_EXT: + return DXGI_FORMAT_R32G32B32A32_FLOAT; + case GL_RGB32F_EXT: + case GL_LUMINANCE32F_EXT: + return DXGI_FORMAT_R32G32B32A32_FLOAT; + case GL_RGBA16F_EXT: + case GL_ALPHA16F_EXT: + case GL_LUMINANCE_ALPHA16F_EXT: + case GL_RGB16F_EXT: + case GL_LUMINANCE16F_EXT: + return DXGI_FORMAT_R16G16B16A16_FLOAT; + case GL_BGRA8_EXT: + return DXGI_FORMAT_B8G8R8A8_UNORM; + case GL_R8_EXT: + return DXGI_FORMAT_R8_UNORM; + case GL_RG8_EXT: + return DXGI_FORMAT_R8G8_UNORM; + case GL_R16F_EXT: + return DXGI_FORMAT_R16_FLOAT; + case GL_RG16F_EXT: + return DXGI_FORMAT_R16G16_FLOAT; + case GL_DEPTH_COMPONENT16: + return DXGI_FORMAT_D16_UNORM; + case GL_DEPTH_COMPONENT32_OES: + case GL_DEPTH24_STENCIL8_OES: + return DXGI_FORMAT_D24_UNORM_S8_UINT; + case GL_NONE: + return DXGI_FORMAT_UNKNOWN; + default: + UNREACHABLE(); + } + + return DXGI_FORMAT_R8G8B8A8_UNORM; +} + +} + +namespace d3d11 +{ + +void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v) +{ + vertex->x = x; + vertex->y = y; + vertex->u = u; + vertex->v = v; +} + +void SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z, + const gl::Color &color) +{ + vertex->x = x; + vertex->y = y; + vertex->z = z; + vertex->r = color.red; + vertex->g = color.green; + vertex->b = color.blue; + vertex->a = color.alpha; +} + +size_t ComputePixelSizeBits(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_R1_UNORM: + return 1; + + case DXGI_FORMAT_A8_UNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_UNORM: + return 8; + + case DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_R16_SINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R8G8_SINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_UNORM: + return 16; + + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_SINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + return 32; + + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + return 64; + + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_SINT: + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_UINT: + return 96; + + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_SINT: + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_UINT: + return 128; + + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + return 4; + + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return 8; + + default: + return 0; + } +} + +size_t ComputeBlockSizeBits(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return ComputePixelSizeBits(format) * 16; + default: + UNREACHABLE(); + return 0; + } +} + +bool IsCompressed(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return true; + case DXGI_FORMAT_UNKNOWN: + UNREACHABLE(); + return false; + default: + return false; + } +} + +unsigned int GetTextureFormatDimensionAlignment(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return 4; + case DXGI_FORMAT_UNKNOWN: + UNREACHABLE(); + return 1; + default: + return 1; + } +} + +bool IsDepthStencilFormat(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_D16_UNORM: + return true; + default: + return false; + } +} + +DXGI_FORMAT GetDepthTextureFormat(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_R32G8X24_TYPELESS; + case DXGI_FORMAT_D32_FLOAT: return DXGI_FORMAT_R32_TYPELESS; + case DXGI_FORMAT_D24_UNORM_S8_UINT: return DXGI_FORMAT_R24G8_TYPELESS; + case DXGI_FORMAT_D16_UNORM: return DXGI_FORMAT_R16_TYPELESS; + default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; + } +} + +DXGI_FORMAT GetDepthShaderResourceFormat(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; + case DXGI_FORMAT_D32_FLOAT: return DXGI_FORMAT_R32_UINT; + case DXGI_FORMAT_D24_UNORM_S8_UINT: return DXGI_FORMAT_R24_UNORM_X8_TYPELESS; + case DXGI_FORMAT_D16_UNORM: return DXGI_FORMAT_R16_UNORM; + default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; + } +} + +HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) +{ +#if defined(_DEBUG) + return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name); +#else + return S_OK; +#endif +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h new file mode 100644 index 0000000000..70ad4fea2b --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h @@ -0,0 +1,95 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// renderer11_utils.h: Conversion functions and other utility routines +// specific to the D3D11 renderer. + +#ifndef LIBGLESV2_RENDERER_RENDERER11_UTILS_H +#define LIBGLESV2_RENDERER_RENDERER11_UTILS_H + +#include "libGLESv2/angletypes.h" + +namespace gl_d3d11 +{ + +D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha); +D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp); +UINT8 ConvertColorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha); + +D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode); + +D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison); +D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled); +UINT8 ConvertStencilMask(GLuint stencilmask); +D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp); + +D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy); +D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap); +FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset); +FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset); + +DXGI_FORMAT ConvertRenderbufferFormat(GLenum format); +DXGI_FORMAT ConvertTextureFormat(GLenum format, D3D_FEATURE_LEVEL featureLevel); +} + +namespace d3d11_gl +{ + +GLenum ConvertBackBufferFormat(DXGI_FORMAT format); +GLenum ConvertDepthStencilFormat(DXGI_FORMAT format); +GLenum ConvertRenderbufferFormat(DXGI_FORMAT format); +GLenum ConvertTextureInternalFormat(DXGI_FORMAT format); + +} + +namespace d3d11 +{ + +struct PositionTexCoordVertex +{ + float x, y; + float u, v; +}; +void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v); + +struct PositionDepthColorVertex +{ + float x, y, z; + float r, g, b, a; +}; +void SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z, + const gl::Color &color); + +size_t ComputePixelSizeBits(DXGI_FORMAT format); +size_t ComputeBlockSizeBits(DXGI_FORMAT format); + +bool IsCompressed(DXGI_FORMAT format); +unsigned int GetTextureFormatDimensionAlignment(DXGI_FORMAT format); + +bool IsDepthStencilFormat(DXGI_FORMAT format); +DXGI_FORMAT GetDepthTextureFormat(DXGI_FORMAT format); +DXGI_FORMAT GetDepthShaderResourceFormat(DXGI_FORMAT format); + +HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name); + +inline bool isDeviceLostError(HRESULT errorCode) +{ + switch (errorCode) + { + case DXGI_ERROR_DEVICE_HUNG: + case DXGI_ERROR_DEVICE_REMOVED: + case DXGI_ERROR_DEVICE_RESET: + case DXGI_ERROR_DRIVER_INTERNAL_ERROR: + case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE: + return true; + default: + return false; + } +} + +} + +#endif // LIBGLESV2_RENDERER_RENDERER11_UTILS_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl new file mode 100644 index 0000000000..cb132dc99c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl @@ -0,0 +1,42 @@ +void VS_Clear( in float3 inPosition : POSITION, in float4 inColor : COLOR, + out float4 outPosition : SV_POSITION, out float4 outColor : COLOR) +{ + outPosition = float4(inPosition, 1.0f); + outColor = inColor; +} + +// Assume we are in SM4+, which has 8 color outputs +struct PS_OutputMultiple +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float4 color3 : SV_TARGET3; +#ifdef SM4 + float4 color4 : SV_TARGET4; + float4 color5 : SV_TARGET5; + float4 color6 : SV_TARGET6; + float4 color7 : SV_TARGET7; +#endif +}; + +PS_OutputMultiple PS_ClearMultiple(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) +{ + PS_OutputMultiple outColor; + outColor.color0 = inColor; + outColor.color1 = inColor; + outColor.color2 = inColor; + outColor.color3 = inColor; +#ifdef SM4 + outColor.color4 = inColor; + outColor.color5 = inColor; + outColor.color6 = inColor; + outColor.color7 = inColor; +#endif + return outColor; +} + +float4 PS_ClearSingle(in float4 inPosition : SV_Position, in float4 inColor : COLOR) : SV_Target0 +{ + return inColor; +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl new file mode 100644 index 0000000000..43b7801efc --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl @@ -0,0 +1,29 @@ +Texture2D Texture : register(t0); +SamplerState Sampler : register(s0); + +void VS_Passthrough( in float2 inPosition : POSITION, in float2 inTexCoord : TEXCOORD0, + out float4 outPosition : SV_POSITION, out float2 outTexCoord : TEXCOORD0) +{ + outPosition = float4(inPosition, 0.0f, 1.0f); + outTexCoord = inTexCoord; +} + +float4 PS_PassthroughRGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return Texture.Sample(Sampler, inTexCoord).rgba; +} + +float4 PS_PassthroughRGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(Texture.Sample(Sampler, inTexCoord).rgb, 1.0f); +} + +float4 PS_PassthroughLum(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(Texture.Sample(Sampler, inTexCoord).rrr, 1.0f); +} + +float4 PS_PassthroughLumAlpha(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return Texture.Sample(Sampler, inTexCoord).rrra; +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.cpp new file mode 100644 index 0000000000..d73df6418d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.cpp @@ -0,0 +1,595 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Blit.cpp: Surface copy utility class. + +#include "libGLESv2/renderer/d3d9/Blit.h" + +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d9/TextureStorage9.h" +#include "libGLESv2/renderer/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" + +namespace +{ +#include "libGLESv2/renderer/d3d9/shaders/compiled/standardvs.h" +#include "libGLESv2/renderer/d3d9/shaders/compiled/flipyvs.h" +#include "libGLESv2/renderer/d3d9/shaders/compiled/passthroughps.h" +#include "libGLESv2/renderer/d3d9/shaders/compiled/luminanceps.h" +#include "libGLESv2/renderer/d3d9/shaders/compiled/componentmaskps.h" + +const BYTE* const g_shaderCode[] = +{ + g_vs20_standardvs, + g_vs20_flipyvs, + g_ps20_passthroughps, + g_ps20_luminanceps, + g_ps20_componentmaskps +}; + +const size_t g_shaderSize[] = +{ + sizeof(g_vs20_standardvs), + sizeof(g_vs20_flipyvs), + sizeof(g_ps20_passthroughps), + sizeof(g_ps20_luminanceps), + sizeof(g_ps20_componentmaskps) +}; +} + +namespace rx +{ +Blit::Blit(rx::Renderer9 *renderer) + : mRenderer(renderer), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedStateBlock(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL) +{ + initGeometry(); + memset(mCompiledShaders, 0, sizeof(mCompiledShaders)); +} + +Blit::~Blit() +{ + if (mSavedStateBlock) mSavedStateBlock->Release(); + if (mQuadVertexBuffer) mQuadVertexBuffer->Release(); + if (mQuadVertexDeclaration) mQuadVertexDeclaration->Release(); + + for (int i = 0; i < SHADER_COUNT; i++) + { + if (mCompiledShaders[i]) + { + mCompiledShaders[i]->Release(); + } + } +} + +void Blit::initGeometry() +{ + static const float quad[] = + { + -1, -1, + -1, 1, + 1, -1, + 1, 1 + }; + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::error(GL_OUT_OF_MEMORY); + } + + void *lockPtr = NULL; + result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0); + + if (FAILED(result) || lockPtr == NULL) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::error(GL_OUT_OF_MEMORY); + } + + memcpy(lockPtr, quad, sizeof(quad)); + mQuadVertexBuffer->Unlock(); + + static const D3DVERTEXELEMENT9 elements[] = + { + { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, + D3DDECL_END() + }; + + result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::error(GL_OUT_OF_MEMORY); + } +} + +template +bool Blit::setShader(ShaderId source, const char *profile, + D3DShaderType *(rx::Renderer9::*createShader)(const DWORD *, size_t length), + HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)) +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + D3DShaderType *shader; + + if (mCompiledShaders[source] != NULL) + { + shader = static_cast(mCompiledShaders[source]); + } + else + { + const BYTE* shaderCode = g_shaderCode[source]; + size_t shaderSize = g_shaderSize[source]; + + shader = (mRenderer->*createShader)(reinterpret_cast(shaderCode), shaderSize); + if (!shader) + { + ERR("Failed to create shader for blit operation"); + return false; + } + + mCompiledShaders[source] = shader; + } + + HRESULT hr = (device->*setShader)(shader); + + if (FAILED(hr)) + { + ERR("Failed to set shader for blit operation"); + return false; + } + + return true; +} + +bool Blit::setVertexShader(ShaderId shader) +{ + return setShader(shader, "vs_2_0", &rx::Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader); +} + +bool Blit::setPixelShader(ShaderId shader) +{ + return setShader(shader, "ps_2_0", &rx::Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader); +} + +RECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const +{ + D3DSURFACE_DESC desc; + surface->GetDesc(&desc); + + RECT rect; + rect.left = 0; + rect.top = 0; + rect.right = desc.Width; + rect.bottom = desc.Height; + + return rect; +} + +bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) +{ + IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source)); + if (!texture) + { + return false; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + saveState(); + + device->SetTexture(0, texture); + device->SetRenderTarget(0, dest); + + setVertexShader(SHADER_VS_STANDARD); + setPixelShader(SHADER_PS_PASSTHROUGH); + + setCommonBlitState(); + device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + + setViewport(getSurfaceRect(dest), 0, 0); + + render(); + + texture->Release(); + + restoreState(); + + return true; +} + +bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) +{ + RenderTarget9 *renderTarget = NULL; + IDirect3DSurface9 *source = NULL; + gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); + + if (colorbuffer) + { + renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); + } + + if (renderTarget) + { + source = renderTarget->getSurface(); + } + + if (!source) + { + ERR("Failed to retrieve the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); + IDirect3DSurface9 *destSurface = storage9->getSurfaceLevel(level, true); + bool result = false; + + if (destSurface) + { + result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); + destSurface->Release(); + } + + source->Release(); + return result; +} + +bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) +{ + RenderTarget9 *renderTarget = NULL; + IDirect3DSurface9 *source = NULL; + gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); + + if (colorbuffer) + { + renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); + } + + if (renderTarget) + { + source = renderTarget->getSurface(); + } + + if (!source) + { + ERR("Failed to retrieve the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); + IDirect3DSurface9 *destSurface = storage9->getCubeMapSurface(target, level, true); + bool result = false; + + if (destSurface) + { + result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); + destSurface->Release(); + } + + source->Release(); + return result; +} + +bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) +{ + if (!dest) + { + return false; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + D3DSURFACE_DESC sourceDesc; + D3DSURFACE_DESC destDesc; + source->GetDesc(&sourceDesc); + dest->GetDesc(&destDesc); + + if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET && + d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect + { + RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)}; + HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::error(GL_OUT_OF_MEMORY, false); + } + } + else + { + return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest); + } + return true; +} + +bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) +{ + IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect); + if (!texture) + { + return false; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + saveState(); + + device->SetTexture(0, texture); + device->SetRenderTarget(0, dest); + + setViewport(sourceRect, xoffset, yoffset); + + setCommonBlitState(); + if (setFormatConvertShaders(destFormat)) + { + render(); + } + + texture->Release(); + + restoreState(); + + return true; +} + +bool Blit::setFormatConvertShaders(GLenum destFormat) +{ + bool okay = setVertexShader(SHADER_VS_STANDARD); + + switch (destFormat) + { + default: UNREACHABLE(); + case GL_RGBA: + case GL_BGRA_EXT: + case GL_RGB: + case GL_ALPHA: + okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK); + break; + + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + okay = okay && setPixelShader(SHADER_PS_LUMINANCE); + break; + } + + if (!okay) + { + return false; + } + + enum { X = 0, Y = 1, Z = 2, W = 3 }; + + // The meaning of this constant depends on the shader that was selected. + // See the shader assembly code above for details. + float psConst0[4] = { 0, 0, 0, 0 }; + + switch (destFormat) + { + default: UNREACHABLE(); + case GL_RGBA: + case GL_BGRA_EXT: + psConst0[X] = 1; + psConst0[Z] = 1; + break; + + case GL_RGB: + psConst0[X] = 1; + psConst0[W] = 1; + break; + + case GL_ALPHA: + psConst0[Z] = 1; + break; + + case GL_LUMINANCE: + psConst0[Y] = 1; + break; + + case GL_LUMINANCE_ALPHA: + psConst0[X] = 1; + break; + } + + mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst0, 1); + + return true; +} + +IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect) +{ + if (!surface) + { + return NULL; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + D3DSURFACE_DESC sourceDesc; + surface->GetDesc(&sourceDesc); + + // Copy the render target into a texture + IDirect3DTexture9 *texture; + HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); + } + + IDirect3DSurface9 *textureSurface; + result = texture->GetSurfaceLevel(0, &textureSurface); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + texture->Release(); + return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); + } + + mRenderer->endScene(); + result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE); + + textureSurface->Release(); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + texture->Release(); + return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); + } + + return texture; +} + +void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset) +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + D3DVIEWPORT9 vp; + vp.X = xoffset; + vp.Y = yoffset; + vp.Width = sourceRect.right - sourceRect.left; + vp.Height = sourceRect.bottom - sourceRect.top; + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + device->SetViewport(&vp); + + float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 }; + device->SetVertexShaderConstantF(0, halfPixelAdjust, 1); +} + +void Blit::setCommonBlitState() +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + device->SetDepthStencilSurface(NULL); + + device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); + device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); + device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); + + device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE); + device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + + RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle + device->SetScissorRect(&scissorRect); + + for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + device->SetStreamSourceFreq(i, 1); + } +} + +void Blit::render() +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float)); + hr = device->SetVertexDeclaration(mQuadVertexDeclaration); + + mRenderer->startScene(); + hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); +} + +void Blit::saveState() +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + HRESULT hr; + + device->GetDepthStencilSurface(&mSavedDepthStencil); + device->GetRenderTarget(0, &mSavedRenderTarget); + + if (mSavedStateBlock == NULL) + { + hr = device->BeginStateBlock(); + ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); + + setCommonBlitState(); + + static const float dummyConst[4] = { 0, 0, 0, 0 }; + + device->SetVertexShader(NULL); + device->SetVertexShaderConstantF(0, dummyConst, 1); + device->SetPixelShader(NULL); + device->SetPixelShaderConstantF(0, dummyConst, 1); + + D3DVIEWPORT9 dummyVp; + dummyVp.X = 0; + dummyVp.Y = 0; + dummyVp.Width = 1; + dummyVp.Height = 1; + dummyVp.MinZ = 0; + dummyVp.MaxZ = 1; + + device->SetViewport(&dummyVp); + + device->SetTexture(0, NULL); + + device->SetStreamSource(0, mQuadVertexBuffer, 0, 0); + + device->SetVertexDeclaration(mQuadVertexDeclaration); + + hr = device->EndStateBlock(&mSavedStateBlock); + ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); + } + + ASSERT(mSavedStateBlock != NULL); + + if (mSavedStateBlock != NULL) + { + hr = mSavedStateBlock->Capture(); + ASSERT(SUCCEEDED(hr)); + } +} + +void Blit::restoreState() +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + device->SetDepthStencilSurface(mSavedDepthStencil); + if (mSavedDepthStencil != NULL) + { + mSavedDepthStencil->Release(); + mSavedDepthStencil = NULL; + } + + device->SetRenderTarget(0, mSavedRenderTarget); + if (mSavedRenderTarget != NULL) + { + mSavedRenderTarget->Release(); + mSavedRenderTarget = NULL; + } + + ASSERT(mSavedStateBlock != NULL); + + if (mSavedStateBlock != NULL) + { + mSavedStateBlock->Apply(); + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.h new file mode 100644 index 0000000000..3718028e66 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.h @@ -0,0 +1,94 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Blit.cpp: Surface copy utility class. + +#ifndef LIBGLESV2_BLIT_H_ +#define LIBGLESV2_BLIT_H_ + +#include "common/angleutils.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer9; +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; + +class Blit +{ + public: + explicit Blit(Renderer9 *renderer); + ~Blit(); + + // Copy from source surface to dest surface. + // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) + bool copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level); + bool copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level); + + // Copy from source surface to dest surface. + // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) + // source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0. + bool formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); + + // 2x2 box filter sample from source to dest. + // Requires that source is RGB(A) and dest has the same format as source. + bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); + + private: + rx::Renderer9 *mRenderer; + + IDirect3DVertexBuffer9 *mQuadVertexBuffer; + IDirect3DVertexDeclaration9 *mQuadVertexDeclaration; + + void initGeometry(); + + bool setFormatConvertShaders(GLenum destFormat); + + bool copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); + IDirect3DTexture9 *copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect); + void setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset); + void setCommonBlitState(); + RECT getSurfaceRect(IDirect3DSurface9 *surface) const; + + // This enum is used to index mCompiledShaders and mShaderSource. + enum ShaderId + { + SHADER_VS_STANDARD, + SHADER_VS_FLIPY, + SHADER_PS_PASSTHROUGH, + SHADER_PS_LUMINANCE, + SHADER_PS_COMPONENTMASK, + SHADER_COUNT + }; + + // This actually contains IDirect3DVertexShader9 or IDirect3DPixelShader9 casted to IUnknown. + IUnknown *mCompiledShaders[SHADER_COUNT]; + + template + bool setShader(ShaderId source, const char *profile, + D3DShaderType *(Renderer9::*createShader)(const DWORD *, size_t length), + HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)); + + bool setVertexShader(ShaderId shader); + bool setPixelShader(ShaderId shader); + void render(); + + void saveState(); + void restoreState(); + IDirect3DStateBlock9 *mSavedStateBlock; + IDirect3DSurface9 *mSavedRenderTarget; + IDirect3DSurface9 *mSavedDepthStencil; + + DISALLOW_COPY_AND_ASSIGN(Blit); +}; +} + +#endif // LIBGLESV2_BLIT_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp new file mode 100644 index 0000000000..9fdc1246f1 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp @@ -0,0 +1,78 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferStorage9.cpp Defines the BufferStorage9 class. + +#include "libGLESv2/renderer/d3d9/BufferStorage9.h" +#include "common/debug.h" + +namespace rx +{ + +BufferStorage9::BufferStorage9() +{ + mMemory = NULL; + mAllocatedSize = 0; + mSize = 0; +} + +BufferStorage9::~BufferStorage9() +{ + delete[] mMemory; +} + +BufferStorage9 *BufferStorage9::makeBufferStorage9(BufferStorage *bufferStorage) +{ + ASSERT(HAS_DYNAMIC_TYPE(BufferStorage9*, bufferStorage)); + return static_cast(bufferStorage); +} + +void *BufferStorage9::getData() +{ + return mMemory; +} + +void BufferStorage9::setData(const void* data, unsigned int size, unsigned int offset) +{ + if (!mMemory || offset + size > mAllocatedSize) + { + unsigned int newAllocatedSize = offset + size; + void *newMemory = new char[newAllocatedSize]; + + if (offset > 0 && mMemory && mAllocatedSize > 0) + { + memcpy(newMemory, mMemory, std::min(offset, mAllocatedSize)); + } + + delete[] mMemory; + mMemory = newMemory; + mAllocatedSize = newAllocatedSize; + } + + mSize = std::max(mSize, offset + size); + if (data) + { + memcpy(reinterpret_cast(mMemory) + offset, data, size); + } +} + +void BufferStorage9::clear() +{ + mSize = 0; +} + +unsigned int BufferStorage9::getSize() const +{ + return mSize; +} + +bool BufferStorage9::supportsDirectBinding() const +{ + return false; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h new file mode 100644 index 0000000000..3e803969bc --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h @@ -0,0 +1,42 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferStorage9.h Defines the BufferStorage9 class. + +#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_ +#define LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_ + +#include "libGLESv2/renderer/BufferStorage.h" + +namespace rx +{ + +class BufferStorage9 : public BufferStorage +{ + public: + BufferStorage9(); + virtual ~BufferStorage9(); + + static BufferStorage9 *makeBufferStorage9(BufferStorage *bufferStorage); + + virtual void *getData(); + virtual void setData(const void* data, unsigned int size, unsigned int offset); + virtual void clear(); + virtual unsigned int getSize() const; + virtual bool supportsDirectBinding() const; + + private: + DISALLOW_COPY_AND_ASSIGN(BufferStorage9); + + void *mMemory; + unsigned int mAllocatedSize; + + unsigned int mSize; +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp new file mode 100644 index 0000000000..639c37b4e4 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp @@ -0,0 +1,135 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Fence9.cpp: Defines the rx::Fence9 class. + +#include "libGLESv2/renderer/d3d9/Fence9.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" + +namespace rx +{ + +Fence9::Fence9(rx::Renderer9 *renderer) +{ + mRenderer = renderer; + mQuery = NULL; +} + +Fence9::~Fence9() +{ + if (mQuery) + { + mRenderer->freeEventQuery(mQuery); + mQuery = NULL; + } +} + +GLboolean Fence9::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 Fence9::setFence(GLenum condition) +{ + if (!mQuery) + { + mQuery = mRenderer->allocateEventQuery(); + if (!mQuery) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + HRESULT result = mQuery->Issue(D3DISSUE_END); + ASSERT(SUCCEEDED(result)); + + setCondition(condition); + setStatus(GL_FALSE); +} + +GLboolean Fence9::testFence() +{ + if (mQuery == NULL) + { + return gl::error(GL_INVALID_OPERATION, GL_TRUE); + } + + HRESULT result = mQuery->GetData(NULL, 0, D3DGETDATA_FLUSH); + + if (d3d9::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); + } + + ASSERT(result == S_OK || result == S_FALSE); + setStatus(result == S_OK); + return getStatus(); +} + +void Fence9::finishFence() +{ + if (mQuery == NULL) + { + return gl::error(GL_INVALID_OPERATION); + } + + while (!testFence()) + { + Sleep(0); + } +} + +void Fence9::getFenceiv(GLenum pname, GLint *params) +{ + if (mQuery == NULL) + { + return gl::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 (getStatus()) + { + params[0] = GL_TRUE; + return; + } + + HRESULT result = mQuery->GetData(NULL, 0, 0); + + if (d3d9::isDeviceLostError(result)) + { + params[0] = GL_TRUE; + mRenderer->notifyDeviceLost(); + return gl::error(GL_OUT_OF_MEMORY); + } + + ASSERT(result == S_OK || result == S_FALSE); + setStatus(result == S_OK); + params[0] = getStatus(); + + break; + } + case GL_FENCE_CONDITION_NV: + params[0] = getCondition(); + break; + default: + return gl::error(GL_INVALID_ENUM); + break; + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.h new file mode 100644 index 0000000000..9f17641e51 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Fence9.h: Defines the rx::Fence9 class which implements rx::FenceImpl. + +#ifndef LIBGLESV2_RENDERER_FENCE9_H_ +#define LIBGLESV2_RENDERER_FENCE9_H_ + +#include "libGLESv2/renderer/FenceImpl.h" + +namespace rx +{ +class Renderer9; + +class Fence9 : public FenceImpl +{ + public: + explicit Fence9(rx::Renderer9 *renderer); + virtual ~Fence9(); + + GLboolean isFence(); + void setFence(GLenum condition); + GLboolean testFence(); + void finishFence(); + void getFenceiv(GLenum pname, GLint *params); + + private: + DISALLOW_COPY_AND_ASSIGN(Fence9); + + rx::Renderer9 *mRenderer; + IDirect3DQuery9 *mQuery; +}; + +} + +#endif // LIBGLESV2_RENDERER_FENCE9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp new file mode 100644 index 0000000000..cd12d8cc9e --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp @@ -0,0 +1,736 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image9.cpp: Implements the rx::Image9 class, which acts as the interface to +// the actual underlying surfaces of a Texture. + +#include "libGLESv2/renderer/d3d9/Image9.h" + +#include "libGLESv2/main.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d9/TextureStorage9.h" + +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/generatemip.h" + +namespace rx +{ + +Image9::Image9() +{ + mSurface = NULL; + mRenderer = NULL; + + mD3DPool = D3DPOOL_SYSTEMMEM; + mD3DFormat = D3DFMT_UNKNOWN; +} + +Image9::~Image9() +{ + if (mSurface) + { + mSurface->Release(); + } +} + +void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface) +{ + D3DSURFACE_DESC destDesc; + HRESULT result = destSurface->GetDesc(&destDesc); + ASSERT(SUCCEEDED(result)); + + D3DSURFACE_DESC sourceDesc; + result = sourceSurface->GetDesc(&sourceDesc); + ASSERT(SUCCEEDED(result)); + + ASSERT(sourceDesc.Format == destDesc.Format); + ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width); + ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height); + + D3DLOCKED_RECT sourceLocked = {0}; + result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY); + ASSERT(SUCCEEDED(result)); + + D3DLOCKED_RECT destLocked = {0}; + result = destSurface->LockRect(&destLocked, NULL, 0); + ASSERT(SUCCEEDED(result)); + + const unsigned char *sourceData = reinterpret_cast(sourceLocked.pBits); + unsigned char *destData = reinterpret_cast(destLocked.pBits); + + if (sourceData && destData) + { + switch (sourceDesc.Format) + { + case D3DFMT_L8: + GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); + break; + case D3DFMT_A8L8: + GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); + break; + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); + break; + case D3DFMT_A16B16G16R16F: + GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); + break; + case D3DFMT_A32B32G32R32F: + GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); + break; + default: + UNREACHABLE(); + break; + } + + destSurface->UnlockRect(); + sourceSurface->UnlockRect(); + } +} + +Image9 *Image9::makeImage9(Image *img) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::Image9*, img)); + return static_cast(img); +} + +void Image9::generateMipmap(Image9 *dest, Image9 *source) +{ + IDirect3DSurface9 *sourceSurface = source->getSurface(); + if (sourceSurface == NULL) + return gl::error(GL_OUT_OF_MEMORY); + + IDirect3DSurface9 *destSurface = dest->getSurface(); + generateMip(destSurface, sourceSurface); + + dest->markDirty(); +} + +void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source) +{ + D3DLOCKED_RECT sourceLock = {0}; + D3DLOCKED_RECT destLock = {0}; + + source->LockRect(&sourceLock, NULL, 0); + dest->LockRect(&destLock, NULL, 0); + + if (sourceLock.pBits && destLock.pBits) + { + D3DSURFACE_DESC desc; + source->GetDesc(&desc); + + int rows = d3d9::IsCompressedFormat(desc.Format) ? desc.Height / 4 : desc.Height; + int bytes = d3d9::ComputeRowSize(desc.Format, desc.Width); + ASSERT(bytes <= sourceLock.Pitch && bytes <= destLock.Pitch); + + for(int i = 0; i < rows; i++) + { + memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes); + } + + source->UnlockRect(); + dest->UnlockRect(); + } + else UNREACHABLE(); +} + +bool Image9::redefine(rx::Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) +{ + if (mWidth != width || + mHeight != height || + mInternalFormat != internalformat || + forceRelease) + { + mRenderer = Renderer9::makeRenderer9(renderer); + + mWidth = width; + mHeight = height; + mInternalFormat = internalformat; + // compute the d3d format that will be used + mD3DFormat = mRenderer->ConvertTextureInternalFormat(internalformat); + mActualFormat = d3d9_gl::GetEquivalentFormat(mD3DFormat); + + if (mSurface) + { + mSurface->Release(); + mSurface = NULL; + } + + return true; + } + + return false; +} + +void Image9::createSurface() +{ + if(mSurface) + { + return; + } + + IDirect3DTexture9 *newTexture = NULL; + IDirect3DSurface9 *newSurface = NULL; + const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM; + const D3DFORMAT d3dFormat = getD3DFormat(); + ASSERT(d3dFormat != D3DFMT_INTZ); // We should never get here for depth textures + + if (mWidth != 0 && mHeight != 0) + { + int levelToFetch = 0; + GLsizei requestWidth = mWidth; + GLsizei requestHeight = mHeight; + gl::MakeValidSize(true, gl::IsCompressed(mInternalFormat), &requestWidth, &requestHeight, &levelToFetch); + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0, d3dFormat, + poolToUse, &newTexture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + ERR("Creating image surface failed."); + return gl::error(GL_OUT_OF_MEMORY); + } + + newTexture->GetSurfaceLevel(levelToFetch, &newSurface); + newTexture->Release(); + } + + mSurface = newSurface; + mDirty = false; + mD3DPool = poolToUse; +} + +HRESULT Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect) +{ + createSurface(); + + HRESULT result = D3DERR_INVALIDCALL; + + if (mSurface) + { + result = mSurface->LockRect(lockedRect, rect, 0); + ASSERT(SUCCEEDED(result)); + + mDirty = true; + } + + return result; +} + +void Image9::unlock() +{ + if (mSurface) + { + HRESULT result = mSurface->UnlockRect(); + ASSERT(SUCCEEDED(result)); + } +} + +bool Image9::isRenderableFormat() const +{ + return TextureStorage9::IsTextureFormatRenderable(getD3DFormat()); +} + +D3DFORMAT Image9::getD3DFormat() const +{ + // this should only happen if the image hasn't been redefined first + // which would be a bug by the caller + ASSERT(mD3DFormat != D3DFMT_UNKNOWN); + + return mD3DFormat; +} + +IDirect3DSurface9 *Image9::getSurface() +{ + createSurface(); + + return mSurface; +} + +void Image9::setManagedSurface(TextureStorageInterface2D *storage, int level) +{ + TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); + setManagedSurface(storage9->getSurfaceLevel(level, false)); +} + +void Image9::setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level) +{ + TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); + setManagedSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false)); +} + +void Image9::setManagedSurface(IDirect3DSurface9 *surface) +{ + D3DSURFACE_DESC desc; + surface->GetDesc(&desc); + ASSERT(desc.Pool == D3DPOOL_MANAGED); + + if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight) + { + if (mSurface) + { + copyLockableSurfaces(surface, mSurface); + mSurface->Release(); + } + + mSurface = surface; + mD3DPool = desc.Pool; + } +} + +bool Image9::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + ASSERT(getSurface() != NULL); + TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); + return updateSurface(storage9->getSurfaceLevel(level, true), xoffset, yoffset, width, height); +} + +bool Image9::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + ASSERT(getSurface() != NULL); + TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); + return updateSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true), xoffset, yoffset, width, height); +} + +bool Image9::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + if (!destSurface) + return false; + + IDirect3DSurface9 *sourceSurface = getSurface(); + + if (sourceSurface && sourceSurface != destSurface) + { + RECT rect; + rect.left = xoffset; + rect.top = yoffset; + rect.right = xoffset + width; + rect.bottom = yoffset + height; + + POINT point = {rect.left, rect.top}; + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + if (mD3DPool == D3DPOOL_MANAGED) + { + D3DSURFACE_DESC desc; + sourceSurface->GetDesc(&desc); + + IDirect3DSurface9 *surf = 0; + HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); + + if (SUCCEEDED(result)) + { + copyLockableSurfaces(surf, sourceSurface); + result = device->UpdateSurface(surf, &rect, destSurface, &point); + ASSERT(SUCCEEDED(result)); + surf->Release(); + } + } + else + { + // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools + HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point); + ASSERT(SUCCEEDED(result)); + } + } + + destSurface->Release(); + return true; +} + +// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input +// into the target pixel rectangle. +void Image9::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLint unpackAlignment, const void *input) +{ + RECT lockRect = + { + xoffset, yoffset, + xoffset + width, yoffset + height + }; + + D3DLOCKED_RECT locked; + HRESULT result = lock(&locked, &lockRect); + if (FAILED(result)) + { + return; + } + + + GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment); + + switch (mInternalFormat) + { + case GL_ALPHA8_EXT: +#if defined(__SSE2__) + if (gl::supportsSSE2()) + { + loadAlphaDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits); + } + else +#endif + { + loadAlphaDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + } + break; + case GL_LUMINANCE8_EXT: + loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_L8); + break; + case GL_ALPHA32F_EXT: + loadAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_LUMINANCE32F_EXT: + loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_ALPHA16F_EXT: + loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_LUMINANCE16F_EXT: + loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_LUMINANCE8_ALPHA8_EXT: + loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_A8L8); + break; + case GL_LUMINANCE_ALPHA32F_EXT: + loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_LUMINANCE_ALPHA16F_EXT: + loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_RGB8_OES: + loadRGBUByteDataToBGRX(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_RGB565: + loadRGB565DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_RGBA8_OES: +#if defined(__SSE2__) + if (gl::supportsSSE2()) + { + loadRGBAUByteDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits); + } + else +#endif + { + loadRGBAUByteDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + } + break; + case GL_RGBA4: + loadRGBA4444DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_RGB5_A1: + loadRGBA5551DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_BGRA8_EXT: + loadBGRADataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D + case GL_RGB32F_EXT: + loadRGBFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_RGB16F_EXT: + loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_RGBA32F_EXT: + loadRGBAFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + case GL_RGBA16F_EXT: + loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); + break; + default: UNREACHABLE(); + } + + unlock(); +} + +void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + const void *input) +{ + ASSERT(xoffset % 4 == 0); + ASSERT(yoffset % 4 == 0); + + RECT lockRect = { + xoffset, yoffset, + xoffset + width, yoffset + height + }; + + D3DLOCKED_RECT locked; + HRESULT result = lock(&locked, &lockRect); + if (FAILED(result)) + { + return; + } + + GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat); + GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat); + int rows = inputSize / inputPitch; + for (int i = 0; i < rows; ++i) + { + memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)input + i * inputPitch), inputPitch); + } + + unlock(); +} + +// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures +void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + RenderTarget9 *renderTarget = NULL; + IDirect3DSurface9 *surface = NULL; + gl::Renderbuffer *colorbuffer = source->getColorbuffer(0); + + if (colorbuffer) + { + renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); + } + + if (renderTarget) + { + surface = renderTarget->getSurface(); + } + + if (!surface) + { + ERR("Failed to retrieve the render target."); + return gl::error(GL_OUT_OF_MEMORY); + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + IDirect3DSurface9 *renderTargetData = NULL; + D3DSURFACE_DESC description; + surface->GetDesc(&description); + + HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL); + + if (FAILED(result)) + { + ERR("Could not create matching destination surface."); + surface->Release(); + return gl::error(GL_OUT_OF_MEMORY); + } + + result = device->GetRenderTargetData(surface, renderTargetData); + + if (FAILED(result)) + { + ERR("GetRenderTargetData unexpectedly failed."); + renderTargetData->Release(); + surface->Release(); + return gl::error(GL_OUT_OF_MEMORY); + } + + RECT sourceRect = {x, y, x + width, y + height}; + RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height}; + + D3DLOCKED_RECT sourceLock = {0}; + result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0); + + if (FAILED(result)) + { + ERR("Failed to lock the source surface (rectangle might be invalid)."); + renderTargetData->Release(); + surface->Release(); + return gl::error(GL_OUT_OF_MEMORY); + } + + D3DLOCKED_RECT destLock = {0}; + result = lock(&destLock, &destRect); + + if (FAILED(result)) + { + ERR("Failed to lock the destination surface (rectangle might be invalid)."); + renderTargetData->UnlockRect(); + renderTargetData->Release(); + surface->Release(); + return gl::error(GL_OUT_OF_MEMORY); + } + + if (destLock.pBits && sourceLock.pBits) + { + unsigned char *source = (unsigned char*)sourceLock.pBits; + unsigned char *dest = (unsigned char*)destLock.pBits; + + switch (description.Format) + { + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + switch(getD3DFormat()) + { + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + for(int y = 0; y < height; y++) + { + memcpy(dest, source, 4 * width); + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + dest[x] = source[x * 4 + 2]; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_A8L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + dest[x * 2 + 0] = source[x * 4 + 2]; + dest[x * 2 + 1] = source[x * 4 + 3]; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + case D3DFMT_R5G6B5: + switch(getD3DFormat()) + { + case D3DFMT_X8R8G8B8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned short rgb = ((unsigned short*)source)[x]; + unsigned char red = (rgb & 0xF800) >> 8; + unsigned char green = (rgb & 0x07E0) >> 3; + unsigned char blue = (rgb & 0x001F) << 3; + dest[x + 0] = blue | (blue >> 5); + dest[x + 1] = green | (green >> 6); + dest[x + 2] = red | (red >> 5); + dest[x + 3] = 0xFF; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned char red = source[x * 2 + 1] & 0xF8; + dest[x] = red | (red >> 5); + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + case D3DFMT_A1R5G5B5: + switch(getD3DFormat()) + { + case D3DFMT_X8R8G8B8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned short argb = ((unsigned short*)source)[x]; + unsigned char red = (argb & 0x7C00) >> 7; + unsigned char green = (argb & 0x03E0) >> 2; + unsigned char blue = (argb & 0x001F) << 3; + dest[x + 0] = blue | (blue >> 5); + dest[x + 1] = green | (green >> 5); + dest[x + 2] = red | (red >> 5); + dest[x + 3] = 0xFF; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_A8R8G8B8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned short argb = ((unsigned short*)source)[x]; + unsigned char red = (argb & 0x7C00) >> 7; + unsigned char green = (argb & 0x03E0) >> 2; + unsigned char blue = (argb & 0x001F) << 3; + unsigned char alpha = (signed short)argb >> 15; + dest[x + 0] = blue | (blue >> 5); + dest[x + 1] = green | (green >> 5); + dest[x + 2] = red | (red >> 5); + dest[x + 3] = alpha; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned char red = source[x * 2 + 1] & 0x7C; + dest[x] = (red << 1) | (red >> 4); + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_A8L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned char red = source[x * 2 + 1] & 0x7C; + dest[x * 2 + 0] = (red << 1) | (red >> 4); + dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + default: + UNREACHABLE(); + } + } + + unlock(); + renderTargetData->UnlockRect(); + + renderTargetData->Release(); + surface->Release(); + + mDirty = true; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.h new file mode 100644 index 0000000000..2fbbca3124 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.h @@ -0,0 +1,79 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image9.h: Defines the rx::Image9 class, which acts as the interface to +// the actual underlying surfaces of a Texture. + +#ifndef LIBGLESV2_RENDERER_IMAGE9_H_ +#define LIBGLESV2_RENDERER_IMAGE9_H_ + +#include "libGLESv2/renderer/Image.h" +#include "common/debug.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer; +class Renderer9; +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; + +class Image9 : public Image +{ + public: + Image9(); + ~Image9(); + + static Image9 *makeImage9(Image *img); + + static void generateMipmap(Image9 *dest, Image9 *source); + static void generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface); + static void copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source); + + virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease); + + virtual bool isRenderableFormat() const; + D3DFORMAT getD3DFormat() const; + + virtual bool isDirty() const {return mSurface && mDirty;} + IDirect3DSurface9 *getSurface(); + + virtual void setManagedSurface(TextureStorageInterface2D *storage, int level); + virtual void setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level); + virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + + virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLint unpackAlignment, const void *input); + virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + const void *input); + + virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + + private: + DISALLOW_COPY_AND_ASSIGN(Image9); + + void createSurface(); + void setManagedSurface(IDirect3DSurface9 *surface); + bool updateSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + + HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect); + void unlock(); + + Renderer9 *mRenderer; + + D3DPOOL mD3DPool; // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable. + D3DFORMAT mD3DFormat; + + IDirect3DSurface9 *mSurface; +}; +} + +#endif // LIBGLESV2_RENDERER_IMAGE9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp new file mode 100644 index 0000000000..7cb5d13a18 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp @@ -0,0 +1,207 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation. + +#include "libGLESv2/renderer/d3d9/IndexBuffer9.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" + +namespace rx +{ + +IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer) +{ + mIndexBuffer = NULL; + mBufferSize = 0; + mIndexType = 0; + mDynamic = false; +} + +IndexBuffer9::~IndexBuffer9() +{ + if (mIndexBuffer) + { + mIndexBuffer->Release(); + mIndexBuffer = NULL; + } +} + +bool IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) +{ + if (mIndexBuffer) + { + mIndexBuffer->Release(); + mIndexBuffer = NULL; + } + + updateSerial(); + + if (bufferSize > 0) + { + D3DFORMAT format; + if (indexType == GL_UNSIGNED_SHORT || indexType == GL_UNSIGNED_BYTE) + { + format = D3DFMT_INDEX16; + } + else if (indexType == GL_UNSIGNED_INT) + { + if (mRenderer->get32BitIndexSupport()) + { + format = D3DFMT_INDEX32; + } + else + { + ERR("Attempted to create a 32-bit index buffer but renderer does not support 32-bit indices."); + return false; + } + } + else + { + ERR("Invalid index type %u.", indexType); + return false; + } + + DWORD usageFlags = D3DUSAGE_WRITEONLY; + if (dynamic) + { + usageFlags |= D3DUSAGE_DYNAMIC; + } + + HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer); + if (FAILED(result)) + { + ERR("Failed to create an index buffer of size %u, result: 0x%08x.", mBufferSize, result); + return false; + } + } + + mBufferSize = bufferSize; + mIndexType = indexType; + mDynamic = dynamic; + + return true; +} + +IndexBuffer9 *IndexBuffer9::makeIndexBuffer9(IndexBuffer *indexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer9*, indexBuffer)); + return static_cast(indexBuffer); +} + +bool IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) +{ + if (mIndexBuffer) + { + DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0; + + void *mapPtr = NULL; + HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags); + if (FAILED(result)) + { + ERR("Index buffer lock failed with error 0x%08x", result); + return false; + } + + *outMappedMemory = mapPtr; + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +bool IndexBuffer9::unmapBuffer() +{ + if (mIndexBuffer) + { + HRESULT result = mIndexBuffer->Unlock(); + if (FAILED(result)) + { + ERR("Index buffer unlock failed with error 0x%08x", result); + return false; + } + + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +GLenum IndexBuffer9::getIndexType() const +{ + return mIndexType; +} + +unsigned int IndexBuffer9::getBufferSize() const +{ + return mBufferSize; +} + +bool IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType) +{ + if (bufferSize > mBufferSize || indexType != mIndexType) + { + return initialize(bufferSize, indexType, mDynamic); + } + else + { + return true; + } +} + +bool IndexBuffer9::discard() +{ + if (mIndexBuffer) + { + void *dummy; + HRESULT result; + + result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); + if (FAILED(result)) + { + ERR("Discard lock failed with error 0x%08x", result); + return false; + } + + result = mIndexBuffer->Unlock(); + if (FAILED(result)) + { + ERR("Discard unlock failed with error 0x%08x", result); + return false; + } + + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +D3DFORMAT IndexBuffer9::getIndexFormat() const +{ + switch (mIndexType) + { + case GL_UNSIGNED_BYTE: return D3DFMT_INDEX16; + case GL_UNSIGNED_SHORT: return D3DFMT_INDEX16; + case GL_UNSIGNED_INT: return D3DFMT_INDEX32; + default: UNREACHABLE(); return D3DFMT_UNKNOWN; + } +} + +IDirect3DIndexBuffer9 * IndexBuffer9::getBuffer() const +{ + return mIndexBuffer; +} + +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h new file mode 100644 index 0000000000..6801867532 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Indexffer9.h: Defines the D3D9 IndexBuffer implementation. + +#ifndef LIBGLESV2_RENDERER_INDEXBUFFER9_H_ +#define LIBGLESV2_RENDERER_INDEXBUFFER9_H_ + +#include "libGLESv2/renderer/IndexBuffer.h" + +namespace rx +{ +class Renderer9; + +class IndexBuffer9 : public IndexBuffer +{ + public: + explicit IndexBuffer9(Renderer9 *const renderer); + virtual ~IndexBuffer9(); + + virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); + + static IndexBuffer9 *makeIndexBuffer9(IndexBuffer *indexBuffer); + + virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); + virtual bool unmapBuffer(); + + virtual GLenum getIndexType() const; + virtual unsigned int getBufferSize() const; + virtual bool setSize(unsigned int bufferSize, GLenum indexType); + + virtual bool discard(); + + D3DFORMAT getIndexFormat() const; + IDirect3DIndexBuffer9 *getBuffer() const; + + private: + DISALLOW_COPY_AND_ASSIGN(IndexBuffer9); + + rx::Renderer9 *const mRenderer; + + IDirect3DIndexBuffer9 *mIndexBuffer; + unsigned int mBufferSize; + GLenum mIndexType; + bool mDynamic; +}; + +} + +#endif // LIBGLESV2_RENDERER_INDEXBUFFER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.cpp new file mode 100644 index 0000000000..72781cbc39 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.cpp @@ -0,0 +1,125 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl. + + +#include "libGLESv2/renderer/d3d9/Query9.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" + +namespace rx +{ + +Query9::Query9(rx::Renderer9 *renderer, GLenum type) : QueryImpl(type) +{ + mRenderer = renderer; + mQuery = NULL; +} + +Query9::~Query9() +{ + if (mQuery) + { + mQuery->Release(); + mQuery = NULL; + } +} + +void Query9::begin() +{ + if (mQuery == NULL) + { + if (FAILED(mRenderer->getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery))) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + HRESULT result = mQuery->Issue(D3DISSUE_BEGIN); + ASSERT(SUCCEEDED(result)); +} + +void Query9::end() +{ + if (mQuery == NULL) + { + return gl::error(GL_INVALID_OPERATION); + } + + HRESULT result = mQuery->Issue(D3DISSUE_END); + ASSERT(SUCCEEDED(result)); + + mStatus = GL_FALSE; + mResult = GL_FALSE; +} + +GLuint Query9::getResult() +{ + if (mQuery != NULL) + { + while (!testQuery()) + { + Sleep(0); + // explicitly check for device loss + // some drivers seem to return S_FALSE even if the device is lost + // instead of D3DERR_DEVICELOST like they should + if (mRenderer->testDeviceLost(true)) + { + return gl::error(GL_OUT_OF_MEMORY, 0); + } + } + } + + return mResult; +} + +GLboolean Query9::isResultAvailable() +{ + if (mQuery != NULL) + { + testQuery(); + } + + return mStatus; +} + +GLboolean Query9::testQuery() +{ + if (mQuery != NULL && mStatus != GL_TRUE) + { + DWORD numPixels = 0; + + HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH); + if (hres == S_OK) + { + mStatus = GL_TRUE; + + switch (getType()) + { + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: + mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; + break; + default: + ASSERT(false); + } + } + else if (d3d9::isDeviceLostError(hres)) + { + mRenderer->notifyDeviceLost(); + return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); + } + + return mStatus; + } + + return GL_TRUE; // prevent blocking when query is null +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.h new file mode 100644 index 0000000000..47eef89336 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Query9.h: Defines the rx::Query9 class which implements rx::QueryImpl. + +#ifndef LIBGLESV2_RENDERER_QUERY9_H_ +#define LIBGLESV2_RENDERER_QUERY9_H_ + +#include "libGLESv2/renderer/QueryImpl.h" + +namespace rx +{ +class Renderer9; + +class Query9 : public QueryImpl +{ + public: + Query9(rx::Renderer9 *renderer, GLenum type); + virtual ~Query9(); + + void begin(); + void end(); + GLuint getResult(); + GLboolean isResultAvailable(); + + private: + DISALLOW_COPY_AND_ASSIGN(Query9); + + GLboolean testQuery(); + + rx::Renderer9 *mRenderer; + IDirect3DQuery9 *mQuery; +}; + +} + +#endif // LIBGLESV2_RENDERER_QUERY9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp new file mode 100644 index 0000000000..090431db99 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp @@ -0,0 +1,113 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9 +// pointers retained by renderbuffers. + +#include "libGLESv2/renderer/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" + +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +RenderTarget9::RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface) +{ + mRenderer = Renderer9::makeRenderer9(renderer); + mRenderTarget = surface; + + if (mRenderTarget) + { + D3DSURFACE_DESC description; + mRenderTarget->GetDesc(&description); + + mWidth = description.Width; + mHeight = description.Height; + + mInternalFormat = d3d9_gl::GetEquivalentFormat(description.Format); + mActualFormat = d3d9_gl::GetEquivalentFormat(description.Format); + mSamples = d3d9_gl::GetSamplesFromMultisampleType(description.MultiSampleType); + } +} + +RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples) +{ + mRenderer = Renderer9::makeRenderer9(renderer); + mRenderTarget = NULL; + + D3DFORMAT requestedFormat = gl_d3d9::ConvertRenderbufferFormat(format); + int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples); + + if (supportedSamples == -1) + { + gl::error(GL_OUT_OF_MEMORY); + + return; + } + + HRESULT result = D3DERR_INVALIDCALL; + + if (width > 0 && height > 0) + { + if (requestedFormat == D3DFMT_D24S8) + { + result = mRenderer->getDevice()->CreateDepthStencilSurface(width, height, requestedFormat, + gl_d3d9::GetMultisampleTypeFromSamples(supportedSamples), + 0, FALSE, &mRenderTarget, NULL); + } + else + { + result = mRenderer->getDevice()->CreateRenderTarget(width, height, requestedFormat, + gl_d3d9::GetMultisampleTypeFromSamples(supportedSamples), + 0, FALSE, &mRenderTarget, NULL); + } + + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) + { + gl::error(GL_OUT_OF_MEMORY); + + return; + } + + ASSERT(SUCCEEDED(result)); + } + + mWidth = width; + mHeight = height; + mInternalFormat = format; + mSamples = supportedSamples; + mActualFormat = d3d9_gl::GetEquivalentFormat(requestedFormat); +} + +RenderTarget9::~RenderTarget9() +{ + if (mRenderTarget) + { + mRenderTarget->Release(); + } +} + +RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget9*, target)); + return static_cast(target); +} + +IDirect3DSurface9 *RenderTarget9::getSurface() +{ + // Caller is responsible for releasing the returned surface reference. + if (mRenderTarget) + { + mRenderTarget->AddRef(); + } + + return mRenderTarget; +} + +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.h new file mode 100644 index 0000000000..faf8ad1c6d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderTarget9.h: Defines a D3D9-specific wrapper for IDirect3DSurface9 pointers +// retained by Renderbuffers. + +#ifndef LIBGLESV2_RENDERER_RENDERTARGET9_H_ +#define LIBGLESV2_RENDERER_RENDERTARGET9_H_ + +#include "libGLESv2/renderer/RenderTarget.h" + +namespace rx +{ +class Renderer; +class Renderer9; + +class RenderTarget9 : public RenderTarget +{ + public: + RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface); + RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples); + virtual ~RenderTarget9(); + + static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget); + IDirect3DSurface9 *getSurface(); + + private: + DISALLOW_COPY_AND_ASSIGN(RenderTarget9); + + IDirect3DSurface9 *mRenderTarget; + + Renderer9 *mRenderer; +}; + +} + +#endif // LIBGLESV2_RENDERER_RENDERTARGET9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp new file mode 100644 index 0000000000..97a10d64bf --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp @@ -0,0 +1,3287 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer. + +#include "libGLESv2/main.h" +#include "libGLESv2/Buffer.h" +#include "libGLESv2/Texture.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/renderer/IndexDataManager.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d9/ShaderExecutable9.h" +#include "libGLESv2/renderer/d3d9/SwapChain9.h" +#include "libGLESv2/renderer/d3d9/TextureStorage9.h" +#include "libGLESv2/renderer/d3d9/Image9.h" +#include "libGLESv2/renderer/d3d9/Blit.h" +#include "libGLESv2/renderer/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d9/VertexBuffer9.h" +#include "libGLESv2/renderer/d3d9/IndexBuffer9.h" +#include "libGLESv2/renderer/d3d9/BufferStorage9.h" +#include "libGLESv2/renderer/d3d9/Query9.h" +#include "libGLESv2/renderer/d3d9/Fence9.h" + +#include "libEGL/Display.h" + +#include "third_party/trace_event/trace_event.h" + +// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros +#define REF_RAST 0 + +// The "Debug This Pixel..." feature in PIX often fails when using the +// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7 +// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file. +#if !defined(ANGLE_ENABLE_D3D9EX) +// Enables use of the IDirect3D9Ex interface, when available +#define ANGLE_ENABLE_D3D9EX 1 +#endif // !defined(ANGLE_ENABLE_D3D9EX) + +namespace rx +{ +static const D3DFORMAT RenderTargetFormats[] = + { + D3DFMT_A1R5G5B5, + // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value. + D3DFMT_A8R8G8B8, + D3DFMT_R5G6B5, + // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format + D3DFMT_X8R8G8B8 + }; + +static const D3DFORMAT DepthStencilFormats[] = + { + D3DFMT_UNKNOWN, + // D3DFMT_D16_LOCKABLE, + D3DFMT_D32, + // D3DFMT_D15S1, + D3DFMT_D24S8, + D3DFMT_D24X8, + // D3DFMT_D24X4S4, + D3DFMT_D16, + // D3DFMT_D32F_LOCKABLE, + // D3DFMT_D24FS8 + }; + +enum +{ + MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256, + MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32, + MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224, + MAX_VARYING_VECTORS_SM2 = 8, + MAX_VARYING_VECTORS_SM3 = 10, + + MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4 +}; + +Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Renderer(display), mDc(hDc), mSoftwareDevice(softwareDevice) +{ + mD3d9Module = NULL; + + mD3d9 = NULL; + mD3d9Ex = NULL; + mDevice = NULL; + mDeviceEx = NULL; + mDeviceWindow = NULL; + mBlit = NULL; + + mAdapter = D3DADAPTER_DEFAULT; + + #if REF_RAST == 1 || defined(FORCE_REF_RAST) + mDeviceType = D3DDEVTYPE_REF; + #else + mDeviceType = D3DDEVTYPE_HAL; + #endif + + mDeviceLost = false; + + mMaxSupportedSamples = 0; + + mMaskedClearSavedState = NULL; + + mVertexDataManager = NULL; + mIndexDataManager = NULL; + mLineLoopIB = NULL; + + mMaxNullColorbufferLRU = 0; + for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) + { + mNullColorbufferCache[i].lruCount = 0; + mNullColorbufferCache[i].width = 0; + mNullColorbufferCache[i].height = 0; + mNullColorbufferCache[i].buffer = NULL; + } +} + +Renderer9::~Renderer9() +{ + if (mDevice) + { + // If the device is lost, reset it first to prevent leaving the driver in an unstable state + if (testDeviceLost(false)) + { + resetDevice(); + } + } + + deinitialize(); +} + +void Renderer9::deinitialize() +{ + releaseDeviceResources(); + + SafeRelease(mDevice); + SafeRelease(mDeviceEx); + SafeRelease(mD3d9); + SafeRelease(mD3d9Ex); + + if (mDeviceWindow) + { + DestroyWindow(mDeviceWindow); + mDeviceWindow = NULL; + } + + if (mD3d9Module) + { + mD3d9Module = NULL; + } + + while (!mMultiSampleSupport.empty()) + { + delete [] mMultiSampleSupport.begin()->second; + mMultiSampleSupport.erase(mMultiSampleSupport.begin()); + } +} + +Renderer9 *Renderer9::makeRenderer9(Renderer *renderer) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer9*, renderer)); + return static_cast(renderer); +} + +EGLint Renderer9::initialize() +{ + if (!initializeCompiler()) + { + return EGL_NOT_INITIALIZED; + } + + if (mSoftwareDevice) + { + TRACE_EVENT0("gpu", "GetModuleHandle_swiftshader"); + mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); + } + else + { + TRACE_EVENT0("gpu", "GetModuleHandle_d3d9"); + mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); + } + + if (mD3d9Module == NULL) + { + ERR("No D3D9 module found - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); + Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); + + // Use Direct3D9Ex if available. Among other things, this version is less + // inclined to report a lost context, for example when the user switches + // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. + if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) + { + TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface"); + ASSERT(mD3d9Ex); + mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast(&mD3d9)); + ASSERT(mD3d9); + } + else + { + TRACE_EVENT0("gpu", "Direct3DCreate9"); + mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); + } + + if (!mD3d9) + { + ERR("Could not create D3D9 device - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + if (mDc != NULL) + { + // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to + } + + HRESULT result; + + // Give up on getting device caps after about one second. + { + TRACE_EVENT0("gpu", "GetDeviceCaps"); + for (int i = 0; i < 10; ++i) + { + result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); + if (SUCCEEDED(result)) + { + break; + } + else if (result == D3DERR_NOTAVAILABLE) + { + Sleep(100); // Give the driver some time to initialize/recover + } + else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from + { + ERR("failed to get device caps (0x%x)\n", result); + return EGL_NOT_INITIALIZED; + } + } + } + + if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0)) + { + ERR("Renderer does not support PS 2.0. aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + // 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) + { + ERR("Renderer does not support stretctrect from textures!\n"); + return EGL_NOT_INITIALIZED; + } + + { + TRACE_EVENT0("gpu", "GetAdapterIdentifier"); + mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); + } + + // ATI cards on XP have problems with non-power-of-two textures. + mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && + !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && + !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) && + !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD); + + // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec + mSupportsTextureFilterAnisotropy = ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2)); + + mMinSwapInterval = 4; + mMaxSwapInterval = 0; + + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) + { + mMinSwapInterval = std::min(mMinSwapInterval, 0); + mMaxSwapInterval = std::max(mMaxSwapInterval, 0); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) + { + mMinSwapInterval = std::min(mMinSwapInterval, 1); + mMaxSwapInterval = std::max(mMaxSwapInterval, 1); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) + { + mMinSwapInterval = std::min(mMinSwapInterval, 2); + mMaxSwapInterval = std::max(mMaxSwapInterval, 2); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) + { + mMinSwapInterval = std::min(mMinSwapInterval, 3); + mMaxSwapInterval = std::max(mMaxSwapInterval, 3); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) + { + mMinSwapInterval = std::min(mMinSwapInterval, 4); + mMaxSwapInterval = std::max(mMaxSwapInterval, 4); + } + + int max = 0; + { + TRACE_EVENT0("gpu", "getMultiSampleSupport"); + for (unsigned int i = 0; i < ArraySize(RenderTargetFormats); ++i) + { + bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; + getMultiSampleSupport(RenderTargetFormats[i], multisampleArray); + mMultiSampleSupport[RenderTargetFormats[i]] = multisampleArray; + + for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) + { + if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) + { + max = j; + } + } + } + } + + { + TRACE_EVENT0("gpu", "getMultiSampleSupport2"); + for (unsigned int i = 0; i < ArraySize(DepthStencilFormats); ++i) + { + if (DepthStencilFormats[i] == D3DFMT_UNKNOWN) + continue; + + bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; + getMultiSampleSupport(DepthStencilFormats[i], multisampleArray); + mMultiSampleSupport[DepthStencilFormats[i]] = multisampleArray; + + for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) + { + if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) + { + max = j; + } + } + } + } + + mMaxSupportedSamples = max; + + static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); + static const TCHAR className[] = TEXT("STATIC"); + + { + TRACE_EVENT0("gpu", "CreateWindowEx"); + mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); + } + + D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); + DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES; + + { + TRACE_EVENT0("gpu", "D3d9_CreateDevice"); + result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); + } + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) + { + return EGL_BAD_ALLOC; + } + + if (FAILED(result)) + { + TRACE_EVENT0("gpu", "D3d9_CreateDevice2"); + result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST); + return EGL_BAD_ALLOC; + } + } + + if (mD3d9Ex) + { + TRACE_EVENT0("gpu", "mDevice_QueryInterface"); + result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx); + ASSERT(SUCCEEDED(result)); + } + + { + TRACE_EVENT0("gpu", "ShaderCache initialize"); + mVertexShaderCache.initialize(mDevice); + mPixelShaderCache.initialize(mDevice); + } + + // Check occlusion query support + IDirect3DQuery9 *occlusionQuery = NULL; + { + TRACE_EVENT0("gpu", "device_CreateQuery"); + if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery) + { + occlusionQuery->Release(); + mOcclusionQuerySupport = true; + } + else + { + mOcclusionQuerySupport = false; + } + } + + // Check event query support + IDirect3DQuery9 *eventQuery = NULL; + { + TRACE_EVENT0("gpu", "device_CreateQuery2"); + if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery) + { + eventQuery->Release(); + mEventQuerySupport = true; + } + else + { + mEventQuerySupport = false; + } + } + + D3DDISPLAYMODE currentDisplayMode; + mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); + + // Check vertex texture support + // Only Direct3D 10 ready devices support all the necessary vertex texture formats. + // We test this using D3D9 by checking support for the R16F format. + mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) && + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, + D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F)); + + // Check depth texture support + // we use INTZ for depth textures in Direct3D9 + // we also want NULL texture support to ensure the we can make depth-only FBOs + // see http://aras-p.info/texts/D3D9GPUHacks.html + mDepthTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, + D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ)) && + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, + D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL)); + + // Check 32 bit floating point texture support + mFloat32FilterSupport = 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)); + + mFloat32RenderSupport = 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 (!mFloat32FilterSupport && !mFloat32RenderSupport) + { + mFloat32TextureSupport = 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 + { + mFloat32TextureSupport = true; + } + + // Check 16 bit floating point texture support + mFloat16FilterSupport = 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)); + + mFloat16RenderSupport = 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 (!mFloat16FilterSupport && !mFloat16RenderSupport) + { + mFloat16TextureSupport = 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 + { + mFloat16TextureSupport = true; + } + + // Check DXT texture support + mDXT1TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1)); + mDXT3TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3)); + mDXT5TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5)); + + // Check luminance[alpha] texture support + mLuminanceTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8)); + mLuminanceAlphaTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8)); + + initializeDevice(); + + return EGL_SUCCESS; +} + +// do any one-time device initialization +// NOTE: this is also needed after a device lost/reset +// to reset the scene status and ensure the default states are reset. +void Renderer9::initializeDevice() +{ + // Permanent non-default states + mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); + mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE); + + if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) + { + mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize); + } + else + { + mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f + } + + markAllStateDirty(); + + mSceneStarted = false; + + ASSERT(!mBlit && !mVertexDataManager && !mIndexDataManager); + mBlit = new Blit(this); + mVertexDataManager = new rx::VertexDataManager(this); + mIndexDataManager = new rx::IndexDataManager(this); +} + +D3DPRESENT_PARAMETERS Renderer9::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; +} + +int Renderer9::generateConfigs(ConfigDesc **configDescList) +{ + D3DDISPLAYMODE currentDisplayMode; + mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); + + unsigned int numRenderFormats = ArraySize(RenderTargetFormats); + unsigned int numDepthFormats = ArraySize(DepthStencilFormats); + (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats]; + int numConfigs = 0; + + for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) + { + D3DFORMAT renderTargetFormat = RenderTargetFormats[formatIndex]; + + HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat); + + if (SUCCEEDED(result)) + { + for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) + { + D3DFORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex]; + HRESULT result = D3D_OK; + + if(depthStencilFormat != D3DFMT_UNKNOWN) + { + result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat); + } + + if (SUCCEEDED(result)) + { + if(depthStencilFormat != D3DFMT_UNKNOWN) + { + result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat); + } + + if (SUCCEEDED(result)) + { + ConfigDesc newConfig; + newConfig.renderTargetFormat = d3d9_gl::ConvertBackBufferFormat(renderTargetFormat); + newConfig.depthStencilFormat = d3d9_gl::ConvertDepthStencilFormat(depthStencilFormat); + newConfig.multiSample = 0; // FIXME: enumerate multi-sampling + newConfig.fastConfig = (currentDisplayMode.Format == renderTargetFormat); + + (*configDescList)[numConfigs++] = newConfig; + } + } + } + } + } + + return numConfigs; +} + +void Renderer9::deleteConfigs(ConfigDesc *configDescList) +{ + delete [] (configDescList); +} + +void Renderer9::startScene() +{ + if (!mSceneStarted) + { + long result = mDevice->BeginScene(); + if (SUCCEEDED(result)) { + // This is defensive checking against the device being + // lost at unexpected times. + mSceneStarted = true; + } + } +} + +void Renderer9::endScene() +{ + if (mSceneStarted) + { + // EndScene can fail if the device was lost, for example due + // to a TDR during a draw call. + mDevice->EndScene(); + mSceneStarted = false; + } +} + +void Renderer9::sync(bool block) +{ + HRESULT result; + + IDirect3DQuery9* query = allocateEventQuery(); + if (!query) + { + return; + } + + result = query->Issue(D3DISSUE_END); + ASSERT(SUCCEEDED(result)); + + do + { + result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); + + if(block && result == S_FALSE) + { + // Keep polling, but allow other threads to do something useful first + Sleep(0); + // explicitly check for device loss + // some drivers seem to return S_FALSE even if the device is lost + // instead of D3DERR_DEVICELOST like they should + if (testDeviceLost(false)) + { + result = D3DERR_DEVICELOST; + } + } + } + while(block && result == S_FALSE); + + freeEventQuery(query); + + if (d3d9::isDeviceLostError(result)) + { + notifyDeviceLost(); + } +} + +SwapChain *Renderer9::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) +{ + return new rx::SwapChain9(this, window, shareHandle, backBufferFormat, depthBufferFormat); +} + +IDirect3DQuery9* Renderer9::allocateEventQuery() +{ + IDirect3DQuery9 *query = NULL; + + if (mEventQueryPool.empty()) + { + HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query); + ASSERT(SUCCEEDED(result)); + } + else + { + query = mEventQueryPool.back(); + mEventQueryPool.pop_back(); + } + + return query; +} + +void Renderer9::freeEventQuery(IDirect3DQuery9* query) +{ + if (mEventQueryPool.size() > 1000) + { + query->Release(); + } + else + { + mEventQueryPool.push_back(query); + } +} + +IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length) +{ + return mVertexShaderCache.create(function, length); +} + +IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length) +{ + return mPixelShaderCache.create(function, length); +} + +HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer) +{ + D3DPOOL Pool = getBufferPool(Usage); + return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL); +} + +VertexBuffer *Renderer9::createVertexBuffer() +{ + return new VertexBuffer9(this); +} + +HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer) +{ + D3DPOOL Pool = getBufferPool(Usage); + return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL); +} + +IndexBuffer *Renderer9::createIndexBuffer() +{ + return new IndexBuffer9(this); +} + +BufferStorage *Renderer9::createBufferStorage() +{ + return new BufferStorage9(); +} + +QueryImpl *Renderer9::createQuery(GLenum type) +{ + return new Query9(this, type); +} + +FenceImpl *Renderer9::createFence() +{ + return new Fence9(this); +} + +void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) +{ + bool *forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates; + gl::SamplerState *appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates; + + if (forceSetSamplers[index] || memcmp(&samplerState, &appliedSamplers[index], sizeof(gl::SamplerState)) != 0) + { + int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; + int d3dSampler = index + d3dSamplerOffset; + + mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS)); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT)); + + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy)); + D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter; + gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.lodOffset); + if (mSupportsTextureFilterAnisotropy) + { + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy); + } + } + + forceSetSamplers[index] = false; + appliedSamplers[index] = samplerState; +} + +void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture) +{ + int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; + int d3dSampler = index + d3dSamplerOffset; + IDirect3DBaseTexture9 *d3dTexture = NULL; + unsigned int serial = 0; + bool forceSetTexture = false; + + unsigned int *appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials; + + if (texture) + { + TextureStorageInterface *texStorage = texture->getNativeTexture(); + if (texStorage) + { + TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage->getStorageInstance()); + d3dTexture = storage9->getBaseTexture(); + } + // If we get NULL back from getBaseTexture here, something went wrong + // in the texture class and we're unexpectedly missing the d3d texture + ASSERT(d3dTexture != NULL); + + serial = texture->getTextureSerial(); + forceSetTexture = texture->hasDirtyImages(); + } + + if (forceSetTexture || appliedSerials[index] != serial) + { + mDevice->SetTexture(d3dSampler, d3dTexture); + } + + appliedSerials[index] = serial; +} + +void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState) +{ + bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0; + + if (rasterStateChanged) + { + // Set the cull mode + if (rasterState.cullFace) + { + mDevice->SetRenderState(D3DRS_CULLMODE, gl_d3d9::ConvertCullMode(rasterState.cullMode, rasterState.frontFace)); + } + else + { + mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + } + + if (rasterState.polygonOffsetFill) + { + if (mCurDepthSize > 0) + { + mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&rasterState.polygonOffsetFactor); + + float depthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast(mCurDepthSize)); + mDevice->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD*)&depthBias); + } + } + else + { + mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); + mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0); + } + + mCurRasterState = rasterState; + } + + mForceSetRasterState = false; +} + +void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask) +{ + bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0; + bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0; + bool sampleMaskChanged = mForceSetBlendState || sampleMask != mCurSampleMask; + + if (blendStateChanged || blendColorChanged) + { + if (blendState.blend) + { + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + + if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && + blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) + { + mDevice->SetRenderState(D3DRS_BLENDFACTOR, gl_d3d9::ConvertColor(blendColor)); + } + else + { + mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha), + gl::unorm<8>(blendColor.alpha), + gl::unorm<8>(blendColor.alpha), + gl::unorm<8>(blendColor.alpha))); + } + + mDevice->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB)); + mDevice->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB)); + mDevice->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB)); + + if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha || + blendState.destBlendRGB != blendState.destBlendAlpha || + blendState.blendEquationRGB != blendState.blendEquationAlpha) + { + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + + mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha)); + mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha)); + mDevice->SetRenderState(D3DRS_BLENDOPALPHA, gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha)); + } + else + { + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); + } + } + else + { + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + } + + if (blendState.sampleAlphaToCoverage) + { + FIXME("Sample alpha to coverage is unimplemented."); + } + + // Set the color mask + bool zeroColorMaskAllowed = getAdapterVendor() != VENDOR_ID_AMD; + // Apparently some ATI cards have a bug where a draw with a zero color + // write mask can cause later draws to have incorrect results. Instead, + // set a nonzero color write mask but modify the blend state so that no + // drawing is done. + // http://code.google.com/p/angleproject/issues/detail?id=169 + + DWORD colorMask = gl_d3d9::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen, + blendState.colorMaskBlue, blendState.colorMaskAlpha); + if (colorMask == 0 && !zeroColorMaskAllowed) + { + // Enable green channel, but set blending so nothing will be drawn. + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN); + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + + mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); + mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + } + else + { + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask); + } + + mDevice->SetRenderState(D3DRS_DITHERENABLE, blendState.dither ? TRUE : FALSE); + + mCurBlendState = blendState; + mCurBlendColor = blendColor; + } + + if (sampleMaskChanged) + { + // Set the multisample mask + mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); + mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast(sampleMask)); + + mCurSampleMask = sampleMask; + } + + mForceSetBlendState = false; +} + +void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW) +{ + bool depthStencilStateChanged = mForceSetDepthStencilState || + memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0; + bool stencilRefChanged = mForceSetDepthStencilState || stencilRef != mCurStencilRef || + stencilBackRef != mCurStencilBackRef; + bool frontFaceCCWChanged = mForceSetDepthStencilState || frontFaceCCW != mCurFrontFaceCCW; + + if (depthStencilStateChanged) + { + if (depthStencilState.depthTest) + { + mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); + mDevice->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthStencilState.depthFunc)); + } + else + { + mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); + } + + mCurDepthStencilState = depthStencilState; + } + + if (depthStencilStateChanged || stencilRefChanged || frontFaceCCWChanged) + { + if (depthStencilState.stencilTest && mCurStencilSize > 0) + { + mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); + mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE); + + // FIXME: Unsupported by D3D9 + const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF; + const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK; + const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK; + if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || + stencilRef != stencilBackRef || + depthStencilState.stencilMask != depthStencilState.stencilBackMask) + { + ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL."); + return gl::error(GL_INVALID_OPERATION); + } + + // get the maximum size of the stencil ref + unsigned int maxStencil = (1 << mCurStencilSize) - 1; + + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, + depthStencilState.stencilWritemask); + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, + gl_d3d9::ConvertComparison(depthStencilState.stencilFunc)); + + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, + (stencilRef < (int)maxStencil) ? stencilRef : maxStencil); + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, + depthStencilState.stencilMask); + + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilFail)); + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthFail)); + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthPass)); + + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, + depthStencilState.stencilBackWritemask); + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, + gl_d3d9::ConvertComparison(depthStencilState.stencilBackFunc)); + + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, + (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil); + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, + depthStencilState.stencilBackMask); + + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackFail)); + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthFail)); + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthPass)); + } + else + { + mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); + } + + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, depthStencilState.depthMask ? TRUE : FALSE); + + mCurStencilRef = stencilRef; + mCurStencilBackRef = stencilBackRef; + mCurFrontFaceCCW = frontFaceCCW; + } + + mForceSetDepthStencilState = false; +} + +void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) +{ + bool scissorChanged = mForceSetScissor || + memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || + enabled != mScissorEnabled; + + if (scissorChanged) + { + if (enabled) + { + RECT rect; + rect.left = gl::clamp(scissor.x, 0, static_cast(mRenderTargetDesc.width)); + rect.top = gl::clamp(scissor.y, 0, static_cast(mRenderTargetDesc.height)); + rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast(mRenderTargetDesc.width)); + rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast(mRenderTargetDesc.height)); + mDevice->SetScissorRect(&rect); + } + + mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, enabled ? TRUE : FALSE); + + mScissorEnabled = enabled; + mCurScissor = scissor; + } + + mForceSetScissor = false; +} + +bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport) +{ + gl::Rectangle actualViewport = viewport; + float actualZNear = gl::clamp01(zNear); + float actualZFar = gl::clamp01(zFar); + if (ignoreViewport) + { + actualViewport.x = 0; + actualViewport.y = 0; + actualViewport.width = mRenderTargetDesc.width; + actualViewport.height = mRenderTargetDesc.height; + actualZNear = 0.0f; + actualZFar = 1.0f; + } + + D3DVIEWPORT9 dxViewport; + dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast(mRenderTargetDesc.width)); + dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast(mRenderTargetDesc.height)); + dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast(mRenderTargetDesc.width) - static_cast(dxViewport.X)); + dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast(mRenderTargetDesc.height) - static_cast(dxViewport.Y)); + dxViewport.MinZ = actualZNear; + dxViewport.MaxZ = actualZFar; + + if (dxViewport.Width <= 0 || dxViewport.Height <= 0) + { + return false; // Nothing to render + } + + float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f); + + bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || + actualZNear != mCurNear || actualZFar != mCurFar || mCurDepthFront != depthFront; + if (viewportChanged) + { + mDevice->SetViewport(&dxViewport); + + mCurViewport = actualViewport; + mCurNear = actualZNear; + mCurFar = actualZFar; + mCurDepthFront = depthFront; + + dx_VertexConstants vc = {0}; + dx_PixelConstants pc = {0}; + + vc.viewAdjust[0] = (float)((actualViewport.width - (int)dxViewport.Width) + 2 * (actualViewport.x - (int)dxViewport.X) - 1) / dxViewport.Width; + vc.viewAdjust[1] = (float)((actualViewport.height - (int)dxViewport.Height) + 2 * (actualViewport.y - (int)dxViewport.Y) - 1) / dxViewport.Height; + vc.viewAdjust[2] = (float)actualViewport.width / dxViewport.Width; + vc.viewAdjust[3] = (float)actualViewport.height / dxViewport.Height; + + pc.viewCoords[0] = actualViewport.width * 0.5f; + pc.viewCoords[1] = actualViewport.height * 0.5f; + pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); + pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); + + pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f; + pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f; + pc.depthFront[2] = depthFront; + + vc.depthRange[0] = actualZNear; + vc.depthRange[1] = actualZFar; + vc.depthRange[2] = actualZFar - actualZNear; + + pc.depthRange[0] = actualZNear; + pc.depthRange[1] = actualZFar; + pc.depthRange[2] = actualZFar - actualZNear; + + if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0) + { + mVertexConstants = vc; + mDxUniformsDirty = true; + } + + if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0) + { + mPixelConstants = pc; + mDxUniformsDirty = true; + } + } + + mForceSetViewport = false; + return true; +} + +bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count) +{ + switch (mode) + { + case GL_POINTS: + mPrimitiveType = D3DPT_POINTLIST; + mPrimitiveCount = count; + break; + case GL_LINES: + mPrimitiveType = D3DPT_LINELIST; + mPrimitiveCount = count / 2; + break; + case GL_LINE_LOOP: + mPrimitiveType = D3DPT_LINESTRIP; + mPrimitiveCount = count - 1; // D3D doesn't support line loops, so we draw the last line separately + break; + case GL_LINE_STRIP: + mPrimitiveType = D3DPT_LINESTRIP; + mPrimitiveCount = count - 1; + break; + case GL_TRIANGLES: + mPrimitiveType = D3DPT_TRIANGLELIST; + mPrimitiveCount = count / 3; + break; + case GL_TRIANGLE_STRIP: + mPrimitiveType = D3DPT_TRIANGLESTRIP; + mPrimitiveCount = count - 2; + break; + case GL_TRIANGLE_FAN: + mPrimitiveType = D3DPT_TRIANGLEFAN; + mPrimitiveCount = count - 2; + break; + default: + return gl::error(GL_INVALID_ENUM, false); + } + + return mPrimitiveCount > 0; +} + + +gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer) +{ + if (!depthbuffer) + { + ERR("Unexpected null depthbuffer for depth-only FBO."); + return NULL; + } + + GLsizei width = depthbuffer->getWidth(); + GLsizei height = depthbuffer->getHeight(); + + // search cached nullcolorbuffers + for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) + { + if (mNullColorbufferCache[i].buffer != NULL && + mNullColorbufferCache[i].width == width && + mNullColorbufferCache[i].height == height) + { + mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU; + return mNullColorbufferCache[i].buffer; + } + } + + gl::Renderbuffer *nullbuffer = new gl::Renderbuffer(this, 0, new gl::Colorbuffer(this, width, height, GL_NONE, 0)); + + // add nullbuffer to the cache + NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0]; + for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) + { + if (mNullColorbufferCache[i].lruCount < oldest->lruCount) + { + oldest = &mNullColorbufferCache[i]; + } + } + + delete oldest->buffer; + oldest->buffer = nullbuffer; + oldest->lruCount = ++mMaxNullColorbufferLRU; + oldest->width = width; + oldest->height = height; + + return nullbuffer; +} + +bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) +{ + // if there is no color attachment we must synthesize a NULL colorattachment + // to keep the D3D runtime happy. This should only be possible if depth texturing. + gl::Renderbuffer *renderbufferObject = NULL; + if (framebuffer->getColorbufferType(0) != GL_NONE) + { + renderbufferObject = framebuffer->getColorbuffer(0); + } + else + { + renderbufferObject = getNullColorbuffer(framebuffer->getDepthbuffer()); + } + if (!renderbufferObject) + { + ERR("unable to locate renderbuffer for FBO."); + return false; + } + + bool renderTargetChanged = false; + unsigned int renderTargetSerial = renderbufferObject->getSerial(); + if (renderTargetSerial != mAppliedRenderTargetSerial) + { + // Apply the render target on the device + IDirect3DSurface9 *renderTargetSurface = NULL; + + RenderTarget *renderTarget = renderbufferObject->getRenderTarget(); + if (renderTarget) + { + renderTargetSurface = RenderTarget9::makeRenderTarget9(renderTarget)->getSurface(); + } + + if (!renderTargetSurface) + { + ERR("render target pointer unexpectedly null."); + return false; // Context must be lost + } + + mDevice->SetRenderTarget(0, renderTargetSurface); + renderTargetSurface->Release(); + + mAppliedRenderTargetSerial = renderTargetSerial; + renderTargetChanged = true; + } + + gl::Renderbuffer *depthStencil = NULL; + unsigned int depthbufferSerial = 0; + unsigned int stencilbufferSerial = 0; + if (framebuffer->getDepthbufferType() != GL_NONE) + { + depthStencil = framebuffer->getDepthbuffer(); + if (!depthStencil) + { + ERR("Depth stencil pointer unexpectedly null."); + return false; + } + + depthbufferSerial = depthStencil->getSerial(); + } + else if (framebuffer->getStencilbufferType() != GL_NONE) + { + depthStencil = framebuffer->getStencilbuffer(); + if (!depthStencil) + { + ERR("Depth stencil pointer unexpectedly null."); + return false; + } + + stencilbufferSerial = depthStencil->getSerial(); + } + + if (depthbufferSerial != mAppliedDepthbufferSerial || + stencilbufferSerial != mAppliedStencilbufferSerial || + !mDepthStencilInitialized) + { + unsigned int depthSize = 0; + unsigned int stencilSize = 0; + + // Apply the depth stencil on the device + if (depthStencil) + { + IDirect3DSurface9 *depthStencilSurface = NULL; + RenderTarget *depthStencilRenderTarget = depthStencil->getDepthStencil(); + + if (depthStencilRenderTarget) + { + depthStencilSurface = RenderTarget9::makeRenderTarget9(depthStencilRenderTarget)->getSurface(); + } + + if (!depthStencilSurface) + { + ERR("depth stencil pointer unexpectedly null."); + return false; // Context must be lost + } + + mDevice->SetDepthStencilSurface(depthStencilSurface); + depthStencilSurface->Release(); + + depthSize = depthStencil->getDepthSize(); + stencilSize = depthStencil->getStencilSize(); + } + else + { + mDevice->SetDepthStencilSurface(NULL); + } + + if (!mDepthStencilInitialized || depthSize != mCurDepthSize) + { + mCurDepthSize = depthSize; + mForceSetRasterState = true; + } + + if (!mDepthStencilInitialized || stencilSize != mCurStencilSize) + { + mCurStencilSize = stencilSize; + mForceSetDepthStencilState = true; + } + + mAppliedDepthbufferSerial = depthbufferSerial; + mAppliedStencilbufferSerial = stencilbufferSerial; + mDepthStencilInitialized = true; + } + + if (renderTargetChanged || !mRenderTargetDescInitialized) + { + mForceSetScissor = true; + mForceSetViewport = true; + + mRenderTargetDesc.width = renderbufferObject->getWidth(); + mRenderTargetDesc.height = renderbufferObject->getHeight(); + mRenderTargetDesc.format = renderbufferObject->getActualFormat(); + mRenderTargetDescInitialized = true; + } + + return true; +} + +GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) +{ + TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; + GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances); + if (err != GL_NO_ERROR) + { + return err; + } + + return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw); +} + +// Applies the indices and element array bindings to the Direct3D 9 device +GLenum Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) +{ + GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); + + if (err == GL_NO_ERROR) + { + // Directly binding the storage buffer is not supported for d3d9 + ASSERT(indexInfo->storage == NULL); + + if (indexInfo->serial != mAppliedIBSerial) + { + IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer); + + mDevice->SetIndices(indexBuffer->getBuffer()); + mAppliedIBSerial = indexInfo->serial; + } + } + + return err; +} + +void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances) +{ + startScene(); + + if (mode == GL_LINE_LOOP) + { + drawLineLoop(count, GL_NONE, NULL, 0, NULL); + } + else if (instances > 0) + { + StaticIndexBufferInterface *countingIB = mIndexDataManager->getCountingIndices(count); + if (countingIB) + { + if (mAppliedIBSerial != countingIB->getSerial()) + { + IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer()); + + mDevice->SetIndices(indexBuffer->getBuffer()); + mAppliedIBSerial = countingIB->getSerial(); + } + + for (int i = 0; i < mRepeatDraw; i++) + { + mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount); + } + } + else + { + ERR("Could not create a counting index buffer for glDrawArraysInstanced."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + else // Regular case + { + mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount); + } +} + +void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/) +{ + startScene(); + + if (mode == GL_POINTS) + { + drawIndexedPoints(count, type, indices, indexInfo.minIndex, elementArrayBuffer); + } + else if (mode == GL_LINE_LOOP) + { + drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer); + } + else + { + for (int i = 0; i < mRepeatDraw; i++) + { + GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; + mDevice->DrawIndexedPrimitive(mPrimitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount); + } + } +} + +void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +{ + // Get the raw indices for an indexed draw + if (type != GL_NONE && elementArrayBuffer) + { + gl::Buffer *indexBuffer = elementArrayBuffer; + BufferStorage *storage = indexBuffer->getStorage(); + intptr_t offset = reinterpret_cast(indices); + indices = static_cast(storage->getData()) + offset; + } + + unsigned int startIndex = 0; + + if (get32BitIndexSupport()) + { + if (!mLineLoopIB) + { + mLineLoopIB = new StreamingIndexBufferInterface(this); + if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) + { + delete mLineLoopIB; + mLineLoopIB = NULL; + + ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned int))) + { + ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); + return gl::error(GL_OUT_OF_MEMORY); + } + + // Checked by Renderer9::applyPrimitiveType + ASSERT(count >= 0); + + const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned int); + if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) + { + ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + void* mappedMemory = NULL; + unsigned int offset = 0; + if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) + { + ERR("Could not map index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + startIndex = static_cast(offset) / 4; + unsigned int *data = reinterpret_cast(mappedMemory); + + switch (type) + { + case GL_NONE: // Non-indexed draw + for (int i = 0; i < count; i++) + { + data[i] = i; + } + data[count] = 0; + break; + case GL_UNSIGNED_BYTE: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_SHORT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_INT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + default: UNREACHABLE(); + } + + if (!mLineLoopIB->unmapBuffer()) + { + ERR("Could not unmap index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + else + { + if (!mLineLoopIB) + { + mLineLoopIB = new StreamingIndexBufferInterface(this); + if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT)) + { + delete mLineLoopIB; + mLineLoopIB = NULL; + + ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + // Checked by Renderer9::applyPrimitiveType + ASSERT(count >= 0); + + if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned short))) + { + ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required."); + return gl::error(GL_OUT_OF_MEMORY); + } + + const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned short); + if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT)) + { + ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + void* mappedMemory = NULL; + unsigned int offset; + if (mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) + { + ERR("Could not map index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + startIndex = static_cast(offset) / 2; + unsigned short *data = reinterpret_cast(mappedMemory); + + switch (type) + { + case GL_NONE: // Non-indexed draw + for (int i = 0; i < count; i++) + { + data[i] = i; + } + data[count] = 0; + break; + case GL_UNSIGNED_BYTE: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_SHORT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_INT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + default: UNREACHABLE(); + } + + if (!mLineLoopIB->unmapBuffer()) + { + ERR("Could not unmap index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + if (mAppliedIBSerial != mLineLoopIB->getSerial()) + { + IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(mLineLoopIB->getIndexBuffer()); + + mDevice->SetIndices(indexBuffer->getBuffer()); + mAppliedIBSerial = mLineLoopIB->getSerial(); + } + + mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count); +} + +template +static void drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices, int minIndex) +{ + for (int i = 0; i < count; i++) + { + unsigned int indexValue = static_cast(static_cast(indices)[i]) - minIndex; + device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1); + } +} + +void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +{ + // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call + // for each individual point. This call is not expected to happen often. + + if (elementArrayBuffer) + { + BufferStorage *storage = elementArrayBuffer->getStorage(); + intptr_t offset = reinterpret_cast(indices); + indices = static_cast(storage->getData()) + offset; + } + + switch (type) + { + case GL_UNSIGNED_BYTE: drawPoints(mDevice, count, indices, minIndex); break; + case GL_UNSIGNED_SHORT: drawPoints(mDevice, count, indices, minIndex); break; + case GL_UNSIGNED_INT: drawPoints(mDevice, count, indices, minIndex); break; + default: UNREACHABLE(); + } +} + +void Renderer9::applyShaders(gl::ProgramBinary *programBinary) +{ + unsigned int programBinarySerial = programBinary->getSerial(); + if (programBinarySerial != mAppliedProgramBinarySerial) + { + ShaderExecutable *vertexExe = programBinary->getVertexExecutable(); + ShaderExecutable *pixelExe = programBinary->getPixelExecutable(); + + IDirect3DVertexShader9 *vertexShader = NULL; + if (vertexExe) vertexShader = ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader(); + + IDirect3DPixelShader9 *pixelShader = NULL; + if (pixelExe) pixelShader = ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader(); + + mDevice->SetPixelShader(pixelShader); + mDevice->SetVertexShader(vertexShader); + programBinary->dirtyAllUniforms(); + mDxUniformsDirty = true; + + mAppliedProgramBinarySerial = programBinarySerial; + } +} + +void Renderer9::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) +{ + for (std::vector::const_iterator ub = uniformArray->begin(), ue = uniformArray->end(); ub != ue; ++ub) + { + gl::Uniform *targetUniform = *ub; + + if (targetUniform->dirty) + { + GLfloat *f = (GLfloat*)targetUniform->data; + GLint *i = (GLint*)targetUniform->data; + + switch (targetUniform->type) + { + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: + break; + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + applyUniformnbv(targetUniform, i); + break; + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: + applyUniformnfv(targetUniform, f); + break; + case GL_INT: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: + applyUniformniv(targetUniform, i); + break; + default: + UNREACHABLE(); + } + + targetUniform->dirty = false; + } + } + + // Driver uniforms + if (mDxUniformsDirty) + { + mDevice->SetVertexShaderConstantF(0, (float*)&mVertexConstants, sizeof(dx_VertexConstants) / sizeof(float[4])); + mDevice->SetPixelShaderConstantF(0, (float*)&mPixelConstants, sizeof(dx_PixelConstants) / sizeof(float[4])); + mDxUniformsDirty = false; + } +} + +void Renderer9::applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v) +{ + if (targetUniform->psRegisterIndex >= 0) + { + mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount); + } + + if (targetUniform->vsRegisterIndex >= 0) + { + mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount); + } +} + +void Renderer9::applyUniformniv(gl::Uniform *targetUniform, const GLint *v) +{ + ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); + GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; + + for (unsigned int i = 0; i < targetUniform->registerCount; i++) + { + vector[i][0] = (GLfloat)v[4 * i + 0]; + vector[i][1] = (GLfloat)v[4 * i + 1]; + vector[i][2] = (GLfloat)v[4 * i + 2]; + vector[i][3] = (GLfloat)v[4 * i + 3]; + } + + applyUniformnfv(targetUniform, (GLfloat*)vector); +} + +void Renderer9::applyUniformnbv(gl::Uniform *targetUniform, const GLint *v) +{ + ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); + GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; + + for (unsigned int i = 0; i < targetUniform->registerCount; i++) + { + vector[i][0] = (v[4 * i + 0] == GL_FALSE) ? 0.0f : 1.0f; + vector[i][1] = (v[4 * i + 1] == GL_FALSE) ? 0.0f : 1.0f; + vector[i][2] = (v[4 * i + 2] == GL_FALSE) ? 0.0f : 1.0f; + vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f; + } + + applyUniformnfv(targetUniform, (GLfloat*)vector); +} + +void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) +{ + D3DCOLOR color = D3DCOLOR_ARGB(gl::unorm<8>(clearParams.colorClearValue.alpha), + gl::unorm<8>(clearParams.colorClearValue.red), + gl::unorm<8>(clearParams.colorClearValue.green), + gl::unorm<8>(clearParams.colorClearValue.blue)); + float depth = gl::clamp01(clearParams.depthClearValue); + int stencil = clearParams.stencilClearValue & 0x000000FF; + + unsigned int stencilUnmasked = 0x0; + if ((clearParams.mask & GL_STENCIL_BUFFER_BIT) && frameBuffer->hasStencil()) + { + unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat()); + stencilUnmasked = (0x1 << stencilSize) - 1; + } + + bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha; + + const bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) && + (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; + const bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) && + !(clearParams.colorMaskRed && clearParams.colorMaskGreen && + clearParams.colorMaskBlue && alphaUnmasked); + + if (needMaskedColorClear || needMaskedStencilClear) + { + // State which is altered in all paths from this point to the clear call is saved. + // State which is altered in only some paths will be flagged dirty in the case that + // that path is taken. + HRESULT hr; + if (mMaskedClearSavedState == NULL) + { + hr = mDevice->BeginStateBlock(); + ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); + + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); + mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); + mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); + mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); + mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); + mDevice->SetPixelShader(NULL); + mDevice->SetVertexShader(NULL); + mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); + mDevice->SetStreamSource(0, NULL, 0, 0); + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); + mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); + mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); + + for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mDevice->SetStreamSourceFreq(i, 1); + } + + hr = mDevice->EndStateBlock(&mMaskedClearSavedState); + ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); + } + + ASSERT(mMaskedClearSavedState != NULL); + + if (mMaskedClearSavedState != NULL) + { + hr = mMaskedClearSavedState->Capture(); + ASSERT(SUCCEEDED(hr)); + } + + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); + mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); + mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); + mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + + if (clearParams.mask & GL_COLOR_BUFFER_BIT) + { + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, + gl_d3d9::ConvertColorMask(clearParams.colorMaskRed, + clearParams.colorMaskGreen, + clearParams.colorMaskBlue, + clearParams.colorMaskAlpha)); + } + else + { + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); + } + + if (stencilUnmasked != 0x0 && (clearParams.mask & GL_STENCIL_BUFFER_BIT)) + { + mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); + mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE); + mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); + mDevice->SetRenderState(D3DRS_STENCILREF, stencil); + mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, clearParams.stencilWriteMask); + mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE); + mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE); + mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); + } + else + { + mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); + } + + mDevice->SetPixelShader(NULL); + mDevice->SetVertexShader(NULL); + mDevice->SetFVF(D3DFVF_XYZRHW); + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); + mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); + mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); + + for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mDevice->SetStreamSourceFreq(i, 1); + } + + float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges + quad[0][0] = -0.5f; + quad[0][1] = mRenderTargetDesc.height - 0.5f; + quad[0][2] = 0.0f; + quad[0][3] = 1.0f; + + quad[1][0] = mRenderTargetDesc.width - 0.5f; + quad[1][1] = mRenderTargetDesc.height - 0.5f; + quad[1][2] = 0.0f; + quad[1][3] = 1.0f; + + quad[2][0] = -0.5f; + quad[2][1] = -0.5f; + quad[2][2] = 0.0f; + quad[2][3] = 1.0f; + + quad[3][0] = mRenderTargetDesc.width - 0.5f; + quad[3][1] = -0.5f; + quad[3][2] = 0.0f; + quad[3][3] = 1.0f; + + startScene(); + mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4])); + + if (clearParams.mask & GL_DEPTH_BUFFER_BIT) + { + mDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); + mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil); + } + + if (mMaskedClearSavedState != NULL) + { + mMaskedClearSavedState->Apply(); + } + } + else if (clearParams.mask) + { + DWORD dxClearFlags = 0; + if (clearParams.mask & GL_COLOR_BUFFER_BIT) + { + dxClearFlags |= D3DCLEAR_TARGET; + } + if (clearParams.mask & GL_DEPTH_BUFFER_BIT) + { + dxClearFlags |= D3DCLEAR_ZBUFFER; + } + if (clearParams.mask & GL_STENCIL_BUFFER_BIT) + { + dxClearFlags |= D3DCLEAR_STENCIL; + } + + mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil); + } +} + +void Renderer9::markAllStateDirty() +{ + mAppliedRenderTargetSerial = 0; + mAppliedDepthbufferSerial = 0; + mAppliedStencilbufferSerial = 0; + mDepthStencilInitialized = false; + mRenderTargetDescInitialized = false; + + mForceSetDepthStencilState = true; + mForceSetRasterState = true; + mForceSetScissor = true; + mForceSetViewport = true; + mForceSetBlendState = true; + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) + { + mForceSetVertexSamplerStates[i] = true; + mCurVertexTextureSerials[i] = 0; + } + for (unsigned int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++) + { + mForceSetPixelSamplerStates[i] = true; + mCurPixelTextureSerials[i] = 0; + } + + mAppliedIBSerial = 0; + mAppliedProgramBinarySerial = 0; + mDxUniformsDirty = true; + + mVertexDeclarationCache.markStateDirty(); +} + +void Renderer9::releaseDeviceResources() +{ + while (!mEventQueryPool.empty()) + { + mEventQueryPool.back()->Release(); + mEventQueryPool.pop_back(); + } + + SafeRelease(mMaskedClearSavedState); + + mVertexShaderCache.clear(); + mPixelShaderCache.clear(); + + SafeDelete(mBlit); + SafeDelete(mVertexDataManager); + SafeDelete(mIndexDataManager); + SafeDelete(mLineLoopIB); + + for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) + { + SafeDelete(mNullColorbufferCache[i].buffer); + } + +} + + +void Renderer9::notifyDeviceLost() +{ + mDeviceLost = true; + mDisplay->notifyDeviceLost(); +} + +bool Renderer9::isDeviceLost() +{ + return mDeviceLost; +} + +// set notify to true to broadcast a message to all contexts of the device loss +bool Renderer9::testDeviceLost(bool notify) +{ + HRESULT status = getDeviceStatusCode(); + bool isLost = FAILED(status); + + if (isLost) + { + // ensure we note the device loss -- + // we'll probably get this done again by notifyDeviceLost + // but best to remember it! + // Note that we don't want to clear the device loss status here + // -- this needs to be done by resetDevice + mDeviceLost = true; + if (notify) + { + notifyDeviceLost(); + } + } + + return isLost; +} + +HRESULT Renderer9::getDeviceStatusCode() +{ + HRESULT status = D3D_OK; + + if (mDeviceEx) + { + status = mDeviceEx->CheckDeviceState(NULL); + } + else if (mDevice) + { + status = mDevice->TestCooperativeLevel(); + } + + return status; +} + +bool Renderer9::testDeviceResettable() +{ + // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted + // DEVICEREMOVED indicates the device has been stopped and must be recreated + switch (getDeviceStatusCode()) + { + case D3DERR_DEVICENOTRESET: + case D3DERR_DEVICEHUNG: + return true; + case D3DERR_DEVICELOST: + return (mDeviceEx != NULL); + case D3DERR_DEVICEREMOVED: + ASSERT(mDeviceEx != NULL); + return isRemovedDeviceResettable(); + default: + return false; + } +} + +bool Renderer9::resetDevice() +{ + releaseDeviceResources(); + + D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); + + HRESULT result = D3D_OK; + bool lost = testDeviceLost(false); + bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED); + + // Device Removed is a feature which is only present with D3D9Ex + ASSERT(mDeviceEx != NULL || !removedDevice); + + for (int attempts = 3; lost && attempts > 0; attempts--) + { + if (removedDevice) + { + // Device removed, which may trigger on driver reinstallation, + // may cause a longer wait other reset attempts before the + // system is ready to handle creating a new device. + Sleep(800); + lost = !resetRemovedDevice(); + } + else if (mDeviceEx) + { + Sleep(500); // Give the graphics driver some CPU time + result = mDeviceEx->ResetEx(&presentParameters, NULL); + lost = testDeviceLost(false); + } + else + { + result = mDevice->TestCooperativeLevel(); + while (result == D3DERR_DEVICELOST) + { + Sleep(100); // Give the graphics driver some CPU time + result = mDevice->TestCooperativeLevel(); + } + + if (result == D3DERR_DEVICENOTRESET) + { + result = mDevice->Reset(&presentParameters); + } + lost = testDeviceLost(false); + } + } + + if (FAILED(result)) + { + ERR("Reset/ResetEx failed multiple times: 0x%08X", result); + return false; + } + + if (removedDevice && lost) + { + ERR("Device lost reset failed multiple times"); + return false; + } + + // If the device was removed, we already finished re-initialization in resetRemovedDevice + if (!removedDevice) + { + // reset device defaults + initializeDevice(); + } + + mDeviceLost = false; + + return true; +} + +bool Renderer9::isRemovedDeviceResettable() const +{ + bool success = false; + +#ifdef ANGLE_ENABLE_D3D9EX + IDirect3D9Ex *d3d9Ex = NULL; + typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); + Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); + + if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &d3d9Ex))) + { + D3DCAPS9 deviceCaps; + HRESULT result = d3d9Ex->GetDeviceCaps(mAdapter, mDeviceType, &deviceCaps); + success = SUCCEEDED(result); + } + + SafeRelease(d3d9Ex); +#else + ASSERT(UNREACHABLE()); +#endif + + return success; +} + +bool Renderer9::resetRemovedDevice() +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554(v=vs.85).aspx: + // The hardware adapter has been removed. Application must destroy the device, do enumeration of + // adapters and create another Direct3D device. If application continues rendering without + // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only. + deinitialize(); + return (initialize() == EGL_SUCCESS); +} + +DWORD Renderer9::getAdapterVendor() const +{ + return mAdapterIdentifier.VendorId; +} + +std::string Renderer9::getRendererDescription() const +{ + std::ostringstream rendererString; + + rendererString << mAdapterIdentifier.Description; + if (getShareHandleSupport()) + { + rendererString << " Direct3D9Ex"; + } + else + { + rendererString << " Direct3D9"; + } + + rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion); + rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion); + + return rendererString.str(); +} + +GUID Renderer9::getAdapterIdentifier() const +{ + return mAdapterIdentifier.DeviceIdentifier; +} + +void Renderer9::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray) +{ + for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++) + { + HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format, + TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL); + + multiSampleArray[multiSampleIndex] = SUCCEEDED(result); + } +} + +bool Renderer9::getBGRATextureSupport() const +{ + // DirectX 9 always supports BGRA + return true; +} + +bool Renderer9::getDXT1TextureSupport() +{ + return mDXT1TextureSupport; +} + +bool Renderer9::getDXT3TextureSupport() +{ + return mDXT3TextureSupport; +} + +bool Renderer9::getDXT5TextureSupport() +{ + return mDXT5TextureSupport; +} + +bool Renderer9::getDepthTextureSupport() const +{ + return mDepthTextureSupport; +} + +bool Renderer9::getFloat32TextureSupport(bool *filtering, bool *renderable) +{ + *filtering = mFloat32FilterSupport; + *renderable = mFloat32RenderSupport; + return mFloat32TextureSupport; +} + +bool Renderer9::getFloat16TextureSupport(bool *filtering, bool *renderable) +{ + *filtering = mFloat16FilterSupport; + *renderable = mFloat16RenderSupport; + return mFloat16TextureSupport; +} + +bool Renderer9::getLuminanceTextureSupport() +{ + return mLuminanceTextureSupport; +} + +bool Renderer9::getLuminanceAlphaTextureSupport() +{ + return mLuminanceAlphaTextureSupport; +} + +bool Renderer9::getTextureFilterAnisotropySupport() const +{ + return mSupportsTextureFilterAnisotropy; +} + +float Renderer9::getTextureMaxAnisotropy() const +{ + if (mSupportsTextureFilterAnisotropy) + { + return static_cast(mDeviceCaps.MaxAnisotropy); + } + return 1.0f; +} + +bool Renderer9::getEventQuerySupport() +{ + return mEventQuerySupport; +} + +unsigned int Renderer9::getMaxVertexTextureImageUnits() const +{ + META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); + return mVertexTextureSupport ? MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 : 0; +} + +unsigned int Renderer9::getMaxCombinedTextureImageUnits() const +{ + return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits(); +} + +unsigned int Renderer9::getReservedVertexUniformVectors() const +{ + return 2; // dx_ViewAdjust and dx_DepthRange. +} + +unsigned int Renderer9::getReservedFragmentUniformVectors() const +{ + return 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange. +} + +unsigned int Renderer9::getMaxVertexUniformVectors() const +{ + return MAX_VERTEX_CONSTANT_VECTORS_D3D9 - getReservedVertexUniformVectors(); +} + +unsigned int Renderer9::getMaxFragmentUniformVectors() const +{ + const int maxPixelConstantVectors = (getMajorShaderModel() >= 3) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 : MAX_PIXEL_CONSTANT_VECTORS_SM2; + + return maxPixelConstantVectors - getReservedFragmentUniformVectors(); +} + +unsigned int Renderer9::getMaxVaryingVectors() const +{ + return (getMajorShaderModel() >= 3) ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2; +} + +bool Renderer9::getNonPower2TextureSupport() const +{ + return mSupportsNonPower2Textures; +} + +bool Renderer9::getOcclusionQuerySupport() const +{ + return mOcclusionQuerySupport; +} + +bool Renderer9::getInstancingSupport() const +{ + return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); +} + +bool Renderer9::getShareHandleSupport() const +{ + // PIX doesn't seem to support using share handles, so disable them. + return (mD3d9Ex != NULL) && !gl::perfActive(); +} + +bool Renderer9::getDerivativeInstructionSupport() const +{ + return (mDeviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0; +} + +bool Renderer9::getPostSubBufferSupport() const +{ + return true; +} + +int Renderer9::getMajorShaderModel() const +{ + return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion); +} + +float Renderer9::getMaxPointSize() const +{ + // Point size clamped at 1.0f for SM2 + return getMajorShaderModel() == 3 ? mDeviceCaps.MaxPointSize : 1.0f; +} + +int Renderer9::getMaxViewportDimension() const +{ + int maxTextureDimension = std::min(std::min(getMaxTextureWidth(), getMaxTextureHeight()), + (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE); + return maxTextureDimension; +} + +int Renderer9::getMaxTextureWidth() const +{ + return (int)mDeviceCaps.MaxTextureWidth; +} + +int Renderer9::getMaxTextureHeight() const +{ + return (int)mDeviceCaps.MaxTextureHeight; +} + +bool Renderer9::get32BitIndexSupport() const +{ + return mDeviceCaps.MaxVertexIndex >= (1 << 16); +} + +DWORD Renderer9::getCapsDeclTypes() const +{ + return mDeviceCaps.DeclTypes; +} + +int Renderer9::getMinSwapInterval() const +{ + return mMinSwapInterval; +} + +int Renderer9::getMaxSwapInterval() const +{ + return mMaxSwapInterval; +} + +int Renderer9::getMaxSupportedSamples() const +{ + return mMaxSupportedSamples; +} + +int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const +{ + if (requested == 0) + { + return requested; + } + + std::map::const_iterator itr = mMultiSampleSupport.find(format); + if (itr == mMultiSampleSupport.end()) + { + if (format == D3DFMT_UNKNOWN) + return 0; + return -1; + } + + for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i) + { + if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE) + { + return i; + } + } + + return -1; +} + +unsigned int Renderer9::getMaxRenderTargets() const +{ + // we do not support MRT in d3d9 + return 1; +} + +D3DFORMAT Renderer9::ConvertTextureInternalFormat(GLint internalformat) +{ + switch (internalformat) + { + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT32_OES: + case GL_DEPTH24_STENCIL8_OES: + return D3DFMT_INTZ; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + return D3DFMT_DXT1; + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + return D3DFMT_DXT3; + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + return D3DFMT_DXT5; + case GL_RGBA32F_EXT: + case GL_RGB32F_EXT: + case GL_ALPHA32F_EXT: + case GL_LUMINANCE32F_EXT: + case GL_LUMINANCE_ALPHA32F_EXT: + return D3DFMT_A32B32G32R32F; + case GL_RGBA16F_EXT: + case GL_RGB16F_EXT: + case GL_ALPHA16F_EXT: + case GL_LUMINANCE16F_EXT: + case GL_LUMINANCE_ALPHA16F_EXT: + return D3DFMT_A16B16G16R16F; + case GL_LUMINANCE8_EXT: + if (getLuminanceTextureSupport()) + { + return D3DFMT_L8; + } + break; + case GL_LUMINANCE8_ALPHA8_EXT: + if (getLuminanceAlphaTextureSupport()) + { + return D3DFMT_A8L8; + } + break; + case GL_RGB8_OES: + case GL_RGB565: + return D3DFMT_X8R8G8B8; + } + + return D3DFMT_A8R8G8B8; +} + +bool Renderer9::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) +{ + bool result = false; + + if (source && dest) + { + TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source->getStorageInstance()); + TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest->getStorageInstance()); + + int levels = source9->levelCount(); + for (int i = 0; i < levels; ++i) + { + IDirect3DSurface9 *srcSurf = source9->getSurfaceLevel(i, false); + IDirect3DSurface9 *dstSurf = dest9->getSurfaceLevel(i, false); + + result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); + + if (srcSurf) srcSurf->Release(); + if (dstSurf) dstSurf->Release(); + + if (!result) + return false; + } + } + + return result; +} + +bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) +{ + bool result = false; + + if (source && dest) + { + TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source->getStorageInstance()); + TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest->getStorageInstance()); + int levels = source9->levelCount(); + for (int f = 0; f < 6; f++) + { + for (int i = 0; i < levels; i++) + { + IDirect3DSurface9 *srcSurf = source9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false); + IDirect3DSurface9 *dstSurf = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true); + + result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); + + if (srcSurf) srcSurf->Release(); + if (dstSurf) dstSurf->Release(); + + if (!result) + return false; + } + } + } + + return result; +} + +D3DPOOL Renderer9::getBufferPool(DWORD usage) const +{ + if (mD3d9Ex != NULL) + { + return D3DPOOL_DEFAULT; + } + else + { + if (!(usage & D3DUSAGE_DYNAMIC)) + { + return D3DPOOL_MANAGED; + } + } + + return D3DPOOL_DEFAULT; +} + +bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) +{ + RECT rect; + rect.left = sourceRect.x; + rect.top = sourceRect.y; + rect.right = sourceRect.x + sourceRect.width; + rect.bottom = sourceRect.y + sourceRect.height; + + return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, level); +} + +bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) +{ + RECT rect; + rect.left = sourceRect.x; + rect.top = sourceRect.y; + rect.right = sourceRect.x + sourceRect.width; + rect.bottom = sourceRect.y + sourceRect.height; + + return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level); +} + +bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect, + bool blitRenderTarget, bool blitDepthStencil) +{ + endScene(); + + if (blitRenderTarget) + { + gl::Renderbuffer *readBuffer = readFramebuffer->getColorbuffer(0); + gl::Renderbuffer *drawBuffer = drawFramebuffer->getColorbuffer(0); + RenderTarget9 *readRenderTarget = NULL; + RenderTarget9 *drawRenderTarget = NULL; + IDirect3DSurface9* readSurface = NULL; + IDirect3DSurface9* drawSurface = NULL; + + if (readBuffer) + { + readRenderTarget = RenderTarget9::makeRenderTarget9(readBuffer->getRenderTarget()); + } + if (drawBuffer) + { + drawRenderTarget = RenderTarget9::makeRenderTarget9(drawBuffer->getRenderTarget()); + } + + if (readRenderTarget) + { + readSurface = readRenderTarget->getSurface(); + } + if (drawRenderTarget) + { + drawSurface = drawRenderTarget->getSurface(); + } + + if (!readSurface || !drawSurface) + { + ERR("Failed to retrieve the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RECT srcRect; + srcRect.left = readRect.x; + srcRect.right = readRect.x + readRect.width; + srcRect.top = readRect.y; + srcRect.bottom = readRect.y + readRect.height; + + RECT dstRect; + dstRect.left = drawRect.x; + dstRect.right = drawRect.x + drawRect.width; + dstRect.top = drawRect.y; + dstRect.bottom = drawRect.y + drawRect.height; + + HRESULT result = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE); + + readSurface->Release(); + drawSurface->Release(); + + if (FAILED(result)) + { + ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); + return false; + } + } + + if (blitDepthStencil) + { + gl::Renderbuffer *readBuffer = readFramebuffer->getDepthOrStencilbuffer(); + gl::Renderbuffer *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer(); + RenderTarget9 *readDepthStencil = NULL; + RenderTarget9 *drawDepthStencil = NULL; + IDirect3DSurface9* readSurface = NULL; + IDirect3DSurface9* drawSurface = NULL; + + if (readBuffer) + { + readDepthStencil = RenderTarget9::makeRenderTarget9(readBuffer->getDepthStencil()); + } + if (drawBuffer) + { + drawDepthStencil = RenderTarget9::makeRenderTarget9(drawBuffer->getDepthStencil()); + } + + if (readDepthStencil) + { + readSurface = readDepthStencil->getSurface(); + } + if (drawDepthStencil) + { + drawSurface = drawDepthStencil->getSurface(); + } + + if (!readSurface || !drawSurface) + { + ERR("Failed to retrieve the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE); + + readSurface->Release(); + drawSurface->Release(); + + if (FAILED(result)) + { + ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); + return false; + } + } + + return true; +} + +void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, + GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) +{ + RenderTarget9 *renderTarget = NULL; + IDirect3DSurface9 *surface = NULL; + gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); + + if (colorbuffer) + { + renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); + } + + if (renderTarget) + { + surface = renderTarget->getSurface(); + } + + if (!surface) + { + // context must be lost + return; + } + + D3DSURFACE_DESC desc; + surface->GetDesc(&desc); + + if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) + { + UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target + surface->Release(); + return gl::error(GL_OUT_OF_MEMORY); + } + + HRESULT result; + IDirect3DSurface9 *systemSurface = NULL; + bool directToPixels = !packReverseRowOrder && packAlignment <= 4 && getShareHandleSupport() && + x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height && + desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE; + if (directToPixels) + { + // Use the pixels ptr as a shared handle to write directly into client's memory + result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, + D3DPOOL_SYSTEMMEM, &systemSurface, &pixels); + if (FAILED(result)) + { + // Try again without the shared handle + directToPixels = false; + } + } + + if (!directToPixels) + { + result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, + D3DPOOL_SYSTEMMEM, &systemSurface, NULL); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + surface->Release(); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + result = mDevice->GetRenderTargetData(surface, systemSurface); + surface->Release(); + surface = NULL; + + if (FAILED(result)) + { + systemSurface->Release(); + + // It turns out that D3D will sometimes produce more error + // codes than those documented. + if (d3d9::isDeviceLostError(result)) + { + notifyDeviceLost(); + return gl::error(GL_OUT_OF_MEMORY); + } + else + { + UNREACHABLE(); + return; + } + + } + + if (directToPixels) + { + systemSurface->Release(); + return; + } + + RECT rect; + rect.left = gl::clamp(x, 0L, static_cast(desc.Width)); + rect.top = gl::clamp(y, 0L, static_cast(desc.Height)); + rect.right = gl::clamp(x + width, 0L, static_cast(desc.Width)); + rect.bottom = gl::clamp(y + height, 0L, static_cast(desc.Height)); + + D3DLOCKED_RECT lock; + result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY); + + if (FAILED(result)) + { + UNREACHABLE(); + systemSurface->Release(); + + return; // No sensible error to generate + } + + unsigned char *dest = (unsigned char*)pixels; + unsigned short *dest16 = (unsigned short*)pixels; + + unsigned char *source; + int inputPitch; + if (packReverseRowOrder) + { + source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); + inputPitch = -lock.Pitch; + } + else + { + source = (unsigned char*)lock.pBits; + inputPitch = lock.Pitch; + } + + unsigned int fastPixelSize = 0; + + if (desc.Format == D3DFMT_A8R8G8B8 && + format == GL_BGRA_EXT && + type == GL_UNSIGNED_BYTE) + { + fastPixelSize = 4; + } + else if ((desc.Format == D3DFMT_A4R4G4B4 && + format == GL_BGRA_EXT && + type == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT) || + (desc.Format == D3DFMT_A1R5G5B5 && + format == GL_BGRA_EXT && + type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT)) + { + fastPixelSize = 2; + } + else if (desc.Format == D3DFMT_A16B16G16R16F && + format == GL_RGBA && + type == GL_HALF_FLOAT_OES) + { + fastPixelSize = 8; + } + else if (desc.Format == D3DFMT_A32B32G32R32F && + format == GL_RGBA && + type == GL_FLOAT) + { + fastPixelSize = 16; + } + + for (int j = 0; j < rect.bottom - rect.top; j++) + { + if (fastPixelSize != 0) + { + // Fast path for formats which require no translation: + // D3DFMT_A8R8G8B8 to BGRA/UNSIGNED_BYTE + // D3DFMT_A4R4G4B4 to BGRA/UNSIGNED_SHORT_4_4_4_4_REV_EXT + // D3DFMT_A1R5G5B5 to BGRA/UNSIGNED_SHORT_1_5_5_5_REV_EXT + // D3DFMT_A16B16G16R16F to RGBA/HALF_FLOAT_OES + // D3DFMT_A32B32G32R32F to RGBA/FLOAT + // + // Note that buffers with no alpha go through the slow path below. + memcpy(dest + j * outputPitch, + source + j * inputPitch, + (rect.right - rect.left) * fastPixelSize); + continue; + } + else if (desc.Format == D3DFMT_A8R8G8B8 && + format == GL_RGBA && + type == GL_UNSIGNED_BYTE) + { + // Fast path for swapping red with blue + for (int i = 0; i < rect.right - rect.left; i++) + { + unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); + *(unsigned int*)(dest + 4 * i + j * outputPitch) = + (argb & 0xFF00FF00) | // Keep alpha and green + (argb & 0x00FF0000) >> 16 | // Move red to blue + (argb & 0x000000FF) << 16; // Move blue to red + } + continue; + } + + for (int i = 0; i < rect.right - rect.left; i++) + { + float r; + float g; + float b; + float a; + + switch (desc.Format) + { + case D3DFMT_R5G6B5: + { + unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch); + + a = 1.0f; + b = (rgb & 0x001F) * (1.0f / 0x001F); + g = (rgb & 0x07E0) * (1.0f / 0x07E0); + r = (rgb & 0xF800) * (1.0f / 0xF800); + } + break; + case D3DFMT_A1R5G5B5: + { + unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch); + + a = (argb & 0x8000) ? 1.0f : 0.0f; + b = (argb & 0x001F) * (1.0f / 0x001F); + g = (argb & 0x03E0) * (1.0f / 0x03E0); + r = (argb & 0x7C00) * (1.0f / 0x7C00); + } + break; + case D3DFMT_A8R8G8B8: + { + unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); + + a = (argb & 0xFF000000) * (1.0f / 0xFF000000); + b = (argb & 0x000000FF) * (1.0f / 0x000000FF); + g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00); + r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000); + } + break; + case D3DFMT_X8R8G8B8: + { + unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch); + + a = 1.0f; + b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF); + g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00); + r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000); + } + break; + case D3DFMT_A2R10G10B10: + { + unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); + + a = (argb & 0xC0000000) * (1.0f / 0xC0000000); + b = (argb & 0x000003FF) * (1.0f / 0x000003FF); + g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00); + r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000); + } + break; + case D3DFMT_A32B32G32R32F: + { + // float formats in D3D are stored rgba, rather than the other way round + r = *((float*)(source + 16 * i + j * inputPitch) + 0); + g = *((float*)(source + 16 * i + j * inputPitch) + 1); + b = *((float*)(source + 16 * i + j * inputPitch) + 2); + a = *((float*)(source + 16 * i + j * inputPitch) + 3); + } + break; + case D3DFMT_A16B16G16R16F: + { + // float formats in D3D are stored rgba, rather than the other way round + r = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 0)); + g = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 1)); + b = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 2)); + a = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 3)); + } + break; + default: + UNIMPLEMENTED(); // FIXME + UNREACHABLE(); + return; + } + + switch (format) + { + case GL_RGBA: + switch (type) + { + case GL_UNSIGNED_BYTE: + dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f); + dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); + dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f); + dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); + break; + default: UNREACHABLE(); + } + break; + case GL_BGRA_EXT: + switch (type) + { + case GL_UNSIGNED_BYTE: + dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f); + dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); + dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f); + dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); + break; + case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: + // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section + // this type is packed as follows: + // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------- + // | 4th | 3rd | 2nd | 1st component | + // -------------------------------------------------------------------------------- + // in the case of BGRA_EXT, B is the first component, G the second, and so forth. + dest16[i + j * outputPitch / sizeof(unsigned short)] = + ((unsigned short)(15 * a + 0.5f) << 12)| + ((unsigned short)(15 * r + 0.5f) << 8) | + ((unsigned short)(15 * g + 0.5f) << 4) | + ((unsigned short)(15 * b + 0.5f) << 0); + break; + case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: + // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section + // this type is packed as follows: + // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------- + // | 4th | 3rd | 2nd | 1st component | + // -------------------------------------------------------------------------------- + // in the case of BGRA_EXT, B is the first component, G the second, and so forth. + dest16[i + j * outputPitch / sizeof(unsigned short)] = + ((unsigned short)( a + 0.5f) << 15) | + ((unsigned short)(31 * r + 0.5f) << 10) | + ((unsigned short)(31 * g + 0.5f) << 5) | + ((unsigned short)(31 * b + 0.5f) << 0); + break; + default: UNREACHABLE(); + } + break; + case GL_RGB: + switch (type) + { + case GL_UNSIGNED_SHORT_5_6_5: + dest16[i + j * outputPitch / sizeof(unsigned short)] = + ((unsigned short)(31 * b + 0.5f) << 0) | + ((unsigned short)(63 * g + 0.5f) << 5) | + ((unsigned short)(31 * r + 0.5f) << 11); + break; + case GL_UNSIGNED_BYTE: + dest[3 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f); + dest[3 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); + dest[3 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f); + break; + default: UNREACHABLE(); + } + break; + default: UNREACHABLE(); + } + } + } + + systemSurface->UnlockRect(); + + systemSurface->Release(); +} + +RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth) +{ + SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); + IDirect3DSurface9 *surface = NULL; + if (depth) + { + surface = swapChain9->getDepthStencil(); + } + else + { + surface = swapChain9->getRenderTarget(); + } + + RenderTarget9 *renderTarget = new RenderTarget9(this, surface); + + return renderTarget; +} + +RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) +{ + RenderTarget9 *renderTarget = new RenderTarget9(this, width, height, format, samples); + return renderTarget; +} + +ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type) +{ + ShaderExecutable9 *executable = NULL; + + switch (type) + { + case rx::SHADER_VERTEX: + { + IDirect3DVertexShader9 *vshader = createVertexShader((DWORD*)function, length); + if (vshader) + { + executable = new ShaderExecutable9(function, length, vshader); + } + } + break; + case rx::SHADER_PIXEL: + { + IDirect3DPixelShader9 *pshader = createPixelShader((DWORD*)function, length); + if (pshader) + { + executable = new ShaderExecutable9(function, length, pshader); + } + } + break; + default: + UNREACHABLE(); + break; + } + + return executable; +} + +ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) +{ + const char *profile = NULL; + + switch (type) + { + case rx::SHADER_VERTEX: + profile = getMajorShaderModel() >= 3 ? "vs_3_0" : "vs_2_0"; + break; + case rx::SHADER_PIXEL: + profile = getMajorShaderModel() >= 3 ? "ps_3_0" : "ps_2_0"; + break; + default: + UNREACHABLE(); + return NULL; + } + + // ANGLE issue 486: + // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization + UINT optimizationFlags = (workaround == ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER ? D3DCOMPILE_SKIP_OPTIMIZATION : ANGLE_COMPILE_OPTIMIZATION_LEVEL); + + ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, optimizationFlags, true); + if (!binary) + return NULL; + + ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type); + binary->Release(); + + return executable; +} + +bool Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) +{ + return mBlit->boxFilter(source, dest); +} + +D3DPOOL Renderer9::getTexturePool(DWORD usage) const +{ + if (mD3d9Ex != NULL) + { + return D3DPOOL_DEFAULT; + } + else + { + if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET))) + { + return D3DPOOL_MANAGED; + } + } + + return D3DPOOL_DEFAULT; +} + +bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged) +{ + if (source && dest) + { + HRESULT result = D3DERR_OUTOFVIDEOMEMORY; + + if (fromManaged) + { + D3DSURFACE_DESC desc; + source->GetDesc(&desc); + + IDirect3DSurface9 *surf = 0; + result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); + + if (SUCCEEDED(result)) + { + Image9::copyLockableSurfaces(surf, source); + result = mDevice->UpdateSurface(surf, NULL, dest, NULL); + surf->Release(); + } + } + else + { + endScene(); + result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE); + } + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return false; + } + } + + return true; +} + +Image *Renderer9::createImage() +{ + return new Image9(); +} + +void Renderer9::generateMipmap(Image *dest, Image *src) +{ + Image9 *src9 = Image9::makeImage9(src); + Image9 *dst9 = Image9::makeImage9(dest); + Image9::generateMipmap(dst9, src9); +} + +TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain) +{ + SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); + return new TextureStorage9_2D(this, swapChain9); +} + +TextureStorage *Renderer9::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) +{ + return new TextureStorage9_2D(this, levels, internalformat, usage, forceRenderable, width, height); +} + +TextureStorage *Renderer9::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) +{ + return new TextureStorage9_Cube(this, levels, internalformat, usage, forceRenderable, size); +} + +bool Renderer9::getLUID(LUID *adapterLuid) const +{ + adapterLuid->HighPart = 0; + adapterLuid->LowPart = 0; + + if (mD3d9Ex) + { + mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid); + return true; + } + + return false; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.h new file mode 100644 index 0000000000..24fd2bdd84 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.h @@ -0,0 +1,356 @@ +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer9.h: Defines a back-end specific class for the D3D9 renderer. + +#ifndef LIBGLESV2_RENDERER_RENDERER9_H_ +#define LIBGLESV2_RENDERER_RENDERER9_H_ + +#include "common/angleutils.h" +#include "libGLESv2/mathutil.h" +#include "libGLESv2/renderer/ShaderCache.h" +#include "libGLESv2/renderer/d3d9/VertexDeclarationCache.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/RenderTarget.h" + +namespace gl +{ +class Renderbuffer; +} + +namespace rx +{ +class VertexDataManager; +class IndexDataManager; +class StreamingIndexBufferInterface; +struct TranslatedAttribute; + +class Renderer9 : public Renderer +{ + public: + Renderer9(egl::Display *display, HDC hDc, bool softwareDevice); + virtual ~Renderer9(); + + static Renderer9 *makeRenderer9(Renderer *renderer); + + virtual EGLint initialize(); + virtual bool resetDevice(); + + virtual int generateConfigs(ConfigDesc **configDescList); + virtual void deleteConfigs(ConfigDesc *configDescList); + + void startScene(); + void endScene(); + + virtual void sync(bool block); + + virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + + IDirect3DQuery9* allocateEventQuery(); + void freeEventQuery(IDirect3DQuery9* query); + + // resource creation + IDirect3DVertexShader9 *createVertexShader(const DWORD *function, size_t length); + IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length); + HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer); + HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer); +#if 0 + void *createTexture2D(); + void *createTextureCube(); + void *createQuery(); + void *createIndexBuffer(); + void *createVertexbuffer(); + + // state setup + void applyShaders(); + void applyConstants(); +#endif + virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); + virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture); + + virtual void setRasterizerState(const gl::RasterizerState &rasterState); + virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, + unsigned int sampleMask); + virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW); + + virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); + virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport); + + virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer); + virtual void applyShaders(gl::ProgramBinary *programBinary); + virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray); + virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount); + virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances); + virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); + + virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances); + virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); + + virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); + + virtual void markAllStateDirty(); + + // lost device + void notifyDeviceLost(); + virtual bool isDeviceLost(); + virtual bool testDeviceLost(bool notify); + virtual bool testDeviceResettable(); + + // Renderer capabilities + IDirect3DDevice9 *getDevice() { return mDevice; } + virtual DWORD getAdapterVendor() const; + virtual std::string getRendererDescription() const; + virtual GUID getAdapterIdentifier() const; + + virtual bool getBGRATextureSupport() const; + virtual bool getDXT1TextureSupport(); + virtual bool getDXT3TextureSupport(); + virtual bool getDXT5TextureSupport(); + virtual bool getEventQuerySupport(); + virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable); + virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable); + virtual bool getLuminanceTextureSupport(); + virtual bool getLuminanceAlphaTextureSupport(); + virtual unsigned int getMaxVertexTextureImageUnits() const; + virtual unsigned int getMaxCombinedTextureImageUnits() const; + virtual unsigned int getReservedVertexUniformVectors() const; + virtual unsigned int getReservedFragmentUniformVectors() const; + virtual unsigned int getMaxVertexUniformVectors() const; + virtual unsigned int getMaxFragmentUniformVectors() const; + virtual unsigned int getMaxVaryingVectors() const; + virtual bool getNonPower2TextureSupport() const; + virtual bool getDepthTextureSupport() const; + virtual bool getOcclusionQuerySupport() const; + virtual bool getInstancingSupport() const; + virtual bool getTextureFilterAnisotropySupport() const; + virtual float getTextureMaxAnisotropy() const; + virtual bool getShareHandleSupport() const; + virtual bool getDerivativeInstructionSupport() const; + virtual bool getPostSubBufferSupport() const; + + virtual int getMajorShaderModel() const; + virtual float getMaxPointSize() const; + virtual int getMaxViewportDimension() const; + virtual int getMaxTextureWidth() const; + virtual int getMaxTextureHeight() const; + virtual bool get32BitIndexSupport() const; + DWORD getCapsDeclTypes() const; + virtual int getMinSwapInterval() const; + virtual int getMaxSwapInterval() const; + + virtual GLsizei getMaxSupportedSamples() const; + int getNearestSupportedSamples(D3DFORMAT format, int requested) const; + + virtual unsigned int getMaxRenderTargets() const; + + D3DFORMAT ConvertTextureInternalFormat(GLint internalformat); + + // Pixel operations + virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source); + virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source); + + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level); + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level); + + virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, + bool blitRenderTarget, bool blitDepthStencil); + virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, + GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels); + + // RenderTarget creation + virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); + virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth); + + // Shader operations + virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type); + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround); + + // Image operations + virtual Image *createImage(); + virtual void generateMipmap(Image *dest, Image *source); + virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); + virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); + virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); + + // Buffer creation + virtual VertexBuffer *createVertexBuffer(); + virtual IndexBuffer *createIndexBuffer(); + virtual BufferStorage *createBufferStorage(); + + // Query and Fence creation + virtual QueryImpl *createQuery(GLenum type); + virtual FenceImpl *createFence(); + + // D3D9-renderer specific methods + bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); + + D3DPOOL getTexturePool(DWORD usage) const; + + virtual bool getLUID(LUID *adapterLuid) const; + + private: + DISALLOW_COPY_AND_ASSIGN(Renderer9); + + void deinitialize(); + + void applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v); + void applyUniformniv(gl::Uniform *targetUniform, const GLint *v); + void applyUniformnbv(gl::Uniform *targetUniform, const GLint *v); + + void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); + void drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); + + void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray); + bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); + gl::Renderbuffer *getNullColorbuffer(gl::Renderbuffer *depthbuffer); + + D3DPOOL getBufferPool(DWORD usage) const; + + HMODULE mD3d9Module; + HDC mDc; + + void initializeDevice(); + D3DPRESENT_PARAMETERS getDefaultPresentParameters(); + void releaseDeviceResources(); + + HRESULT getDeviceStatusCode(); + bool isRemovedDeviceResettable() const; + bool resetRemovedDevice(); + + UINT mAdapter; + D3DDEVTYPE mDeviceType; + bool mSoftwareDevice; // FIXME: Deprecate + IDirect3D9 *mD3d9; // Always valid after successful initialization. + IDirect3D9Ex *mD3d9Ex; // Might be null if D3D9Ex is not supported. + IDirect3DDevice9 *mDevice; + IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported. + + Blit *mBlit; + + HWND mDeviceWindow; + + bool mDeviceLost; + D3DCAPS9 mDeviceCaps; + D3DADAPTER_IDENTIFIER9 mAdapterIdentifier; + + D3DPRIMITIVETYPE mPrimitiveType; + int mPrimitiveCount; + GLsizei mRepeatDraw; + + bool mSceneStarted; + bool mSupportsNonPower2Textures; + bool mSupportsTextureFilterAnisotropy; + int mMinSwapInterval; + int mMaxSwapInterval; + + bool mOcclusionQuerySupport; + bool mEventQuerySupport; + bool mVertexTextureSupport; + + bool mDepthTextureSupport; + + bool mFloat32TextureSupport; + bool mFloat32FilterSupport; + bool mFloat32RenderSupport; + + bool mFloat16TextureSupport; + bool mFloat16FilterSupport; + bool mFloat16RenderSupport; + + bool mDXT1TextureSupport; + bool mDXT3TextureSupport; + bool mDXT5TextureSupport; + + bool mLuminanceTextureSupport; + bool mLuminanceAlphaTextureSupport; + + std::map mMultiSampleSupport; + GLsizei mMaxSupportedSamples; + + // current render target states + unsigned int mAppliedRenderTargetSerial; + unsigned int mAppliedDepthbufferSerial; + unsigned int mAppliedStencilbufferSerial; + bool mDepthStencilInitialized; + bool mRenderTargetDescInitialized; + rx::RenderTarget::Desc mRenderTargetDesc; + unsigned int mCurStencilSize; + unsigned int mCurDepthSize; + + IDirect3DStateBlock9 *mMaskedClearSavedState; + + // previously set render states + bool mForceSetDepthStencilState; + gl::DepthStencilState mCurDepthStencilState; + int mCurStencilRef; + int mCurStencilBackRef; + bool mCurFrontFaceCCW; + + bool mForceSetRasterState; + gl::RasterizerState mCurRasterState; + + bool mForceSetScissor; + gl::Rectangle mCurScissor; + bool mScissorEnabled; + + bool mForceSetViewport; + gl::Rectangle mCurViewport; + float mCurNear; + float mCurFar; + float mCurDepthFront; + + bool mForceSetBlendState; + gl::BlendState mCurBlendState; + gl::Color mCurBlendColor; + GLuint mCurSampleMask; + + // Currently applied sampler states + bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + gl::SamplerState mCurVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + + bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; + gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; + + // Currently applied textures + unsigned int mCurVertexTextureSerials[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS]; + + unsigned int mAppliedIBSerial; + unsigned int mAppliedProgramBinarySerial; + + rx::dx_VertexConstants mVertexConstants; + rx::dx_PixelConstants mPixelConstants; + bool mDxUniformsDirty; + + // A pool of event queries that are currently unused. + std::vector mEventQueryPool; + VertexShaderCache mVertexShaderCache; + PixelShaderCache mPixelShaderCache; + + VertexDataManager *mVertexDataManager; + VertexDeclarationCache mVertexDeclarationCache; + + IndexDataManager *mIndexDataManager; + StreamingIndexBufferInterface *mLineLoopIB; + + enum { NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12 }; + struct NullColorbufferCacheEntry + { + UINT lruCount; + int width; + int height; + gl::Renderbuffer *buffer; + } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES]; + UINT mMaxNullColorbufferLRU; + +}; + +} +#endif // LIBGLESV2_RENDERER_RENDERER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp new file mode 100644 index 0000000000..5decf9664d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp @@ -0,0 +1,60 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderExecutable9.cpp: Implements a D3D9-specific class to contain shader +// executable implementation details. + +#include "libGLESv2/renderer/d3d9/ShaderExecutable9.h" + +#include "common/debug.h" + +namespace rx +{ + +ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable) + : ShaderExecutable(function, length) +{ + mPixelExecutable = executable; + mVertexExecutable = NULL; +} + +ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable) + : ShaderExecutable(function, length) +{ + mVertexExecutable = executable; + mPixelExecutable = NULL; +} + +ShaderExecutable9::~ShaderExecutable9() +{ + if (mVertexExecutable) + { + mVertexExecutable->Release(); + } + if (mPixelExecutable) + { + mPixelExecutable->Release(); + } +} + +ShaderExecutable9 *ShaderExecutable9::makeShaderExecutable9(ShaderExecutable *executable) +{ + ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable9*, executable)); + return static_cast(executable); +} + +IDirect3DVertexShader9 *ShaderExecutable9::getVertexShader() const +{ + return mVertexExecutable; +} + +IDirect3DPixelShader9 *ShaderExecutable9::getPixelShader() const +{ + return mPixelExecutable; +} + +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h new file mode 100644 index 0000000000..fa1e6c2844 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderExecutable9.h: Defines a D3D9-specific class to contain shader +// executable implementation details. + +#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ +#define LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ + +#include "libGLESv2/renderer/ShaderExecutable.h" + +namespace rx +{ + +class ShaderExecutable9 : public ShaderExecutable +{ + public: + ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable); + ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable); + virtual ~ShaderExecutable9(); + + static ShaderExecutable9 *makeShaderExecutable9(ShaderExecutable *executable); + + IDirect3DPixelShader9 *getPixelShader() const; + IDirect3DVertexShader9 *getVertexShader() const; + + private: + DISALLOW_COPY_AND_ASSIGN(ShaderExecutable9); + + IDirect3DPixelShader9 *mPixelExecutable; + IDirect3DVertexShader9 *mVertexExecutable; +}; + +} + +#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp new file mode 100644 index 0000000000..dd8895d18d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp @@ -0,0 +1,445 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain. + +#include "libGLESv2/renderer/d3d9/SwapChain9.h" +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" + +namespace rx +{ + +SwapChain9::SwapChain9(Renderer9 *renderer, HWND window, HANDLE shareHandle, + GLenum backBufferFormat, GLenum depthBufferFormat) + : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) +{ + mSwapChain = NULL; + mBackBuffer = NULL; + mDepthStencil = NULL; + mRenderTarget = NULL; + mOffscreenTexture = NULL; + mWidth = -1; + mHeight = -1; + mSwapInterval = -1; +} + +SwapChain9::~SwapChain9() +{ + release(); +} + +void SwapChain9::release() +{ + if (mSwapChain) + { + mSwapChain->Release(); + mSwapChain = NULL; + } + + if (mBackBuffer) + { + mBackBuffer->Release(); + mBackBuffer = NULL; + } + + if (mDepthStencil) + { + mDepthStencil->Release(); + mDepthStencil = NULL; + } + + if (mRenderTarget) + { + mRenderTarget->Release(); + mRenderTarget = NULL; + } + + if (mOffscreenTexture) + { + mOffscreenTexture->Release(); + mOffscreenTexture = NULL; + } + + if (mWindow) + mShareHandle = NULL; +} + +static DWORD convertInterval(EGLint interval) +{ +#if ANGLE_FORCE_VSYNC_OFF + return D3DPRESENT_INTERVAL_IMMEDIATE; +#else + switch(interval) + { + case 0: return D3DPRESENT_INTERVAL_IMMEDIATE; + case 1: return D3DPRESENT_INTERVAL_ONE; + case 2: return D3DPRESENT_INTERVAL_TWO; + case 3: return D3DPRESENT_INTERVAL_THREE; + case 4: return D3DPRESENT_INTERVAL_FOUR; + default: UNREACHABLE(); + } + + return D3DPRESENT_INTERVAL_DEFAULT; +#endif +} + +EGLint SwapChain9::resize(int backbufferWidth, int backbufferHeight) +{ + // D3D9 does not support resizing swap chains without recreating them + return reset(backbufferWidth, backbufferHeight, mSwapInterval); +} + +EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + if (device == NULL) + { + return EGL_BAD_ACCESS; + } + + // Evict all non-render target textures to system memory and release all resources + // before reallocating them to free up as much video memory as possible. + device->EvictManagedResources(); + + HRESULT result; + + // Release specific resources to free up memory for the new render target, while the + // old render target still exists for the purpose of preserving its contents. + if (mSwapChain) + { + mSwapChain->Release(); + mSwapChain = NULL; + } + + if (mBackBuffer) + { + mBackBuffer->Release(); + mBackBuffer = NULL; + } + + if (mOffscreenTexture) + { + mOffscreenTexture->Release(); + mOffscreenTexture = NULL; + } + + if (mDepthStencil) + { + mDepthStencil->Release(); + mDepthStencil = NULL; + } + + HANDLE *pShareHandle = NULL; + if (!mWindow && mRenderer->getShareHandleSupport()) + { + pShareHandle = &mShareHandle; + } + + result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, + gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat), D3DPOOL_DEFAULT, + &mOffscreenTexture, pShareHandle); + if (FAILED(result)) + { + ERR("Could not create offscreen texture: %08lX", result); + release(); + + if (d3d9::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + + IDirect3DSurface9 *oldRenderTarget = mRenderTarget; + + result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget); + ASSERT(SUCCEEDED(result)); + + if (oldRenderTarget) + { + RECT rect = + { + 0, 0, + mWidth, mHeight + }; + + if (rect.right > static_cast(backbufferWidth)) + { + rect.right = backbufferWidth; + } + + if (rect.bottom > static_cast(backbufferHeight)) + { + rect.bottom = backbufferHeight; + } + + mRenderer->endScene(); + + result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE); + ASSERT(SUCCEEDED(result)); + + oldRenderTarget->Release(); + } + + if (mWindow) + { + D3DPRESENT_PARAMETERS presentParameters = {0}; + presentParameters.AutoDepthStencilFormat = gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat); + presentParameters.BackBufferCount = 1; + presentParameters.BackBufferFormat = gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat); + presentParameters.EnableAutoDepthStencil = FALSE; + presentParameters.Flags = 0; + presentParameters.hDeviceWindow = mWindow; + presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented + presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented + presentParameters.PresentationInterval = convertInterval(swapInterval); + presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + presentParameters.Windowed = TRUE; + presentParameters.BackBufferWidth = backbufferWidth; + presentParameters.BackBufferHeight = backbufferHeight; + + // http://crbug.com/140239 + // http://crbug.com/143434 + // + // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width + // when using the integrated Intel. This rounds the width up rather than down. + // + // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID + // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur. + if (mRenderer->getAdapterVendor() == VENDOR_ID_INTEL) + { + presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64; + } + + result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST); + + ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); + release(); + + if (d3d9::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + + result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); + ASSERT(SUCCEEDED(result)); + InvalidateRect(mWindow, NULL, FALSE); + } + + if (mDepthBufferFormat != GL_NONE) + { + result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, + gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat), + D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL); + + ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); + release(); + + if (d3d9::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + mSwapInterval = swapInterval; + + return EGL_SUCCESS; +} + +// parameters should be validated/clamped by caller +EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +{ + if (!mSwapChain) + { + return EGL_SUCCESS; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + // Disable all pipeline operations + device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); + device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + device->SetRenderState(D3DRS_STENCILENABLE, FALSE); + device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); + device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); + device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); + device->SetPixelShader(NULL); + device->SetVertexShader(NULL); + + device->SetRenderTarget(0, mBackBuffer); + device->SetDepthStencilSurface(NULL); + + device->SetTexture(0, mOffscreenTexture); + device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); + + for (UINT streamIndex = 0; streamIndex < gl::MAX_VERTEX_ATTRIBS; streamIndex++) + { + device->SetStreamSourceFreq(streamIndex, 1); + } + + D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f}; + device->SetViewport(&viewport); + + float x1 = x - 0.5f; + float y1 = (mHeight - y - height) - 0.5f; + float x2 = (x + width) - 0.5f; + float y2 = (mHeight - y) - 0.5f; + + float u1 = x / float(mWidth); + float v1 = y / float(mHeight); + float u2 = (x + width) / float(mWidth); + float v2 = (y + height) / float(mHeight); + + float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2}, + {x2, y1, 0.0f, 1.0f, u2, v2}, + {x2, y2, 0.0f, 1.0f, u2, v1}, + {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v + + mRenderer->startScene(); + device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); + mRenderer->endScene(); + + device->SetTexture(0, NULL); + + RECT rect = + { + x, mHeight - y - height, + x + width, mHeight - y + }; + + HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0); + + mRenderer->markAllStateDirty(); + + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) + { + return EGL_BAD_ALLOC; + } + + // http://crbug.com/313210 + // If our swap failed, trigger a device lost event. Resetting will work around an AMD-specific + // device removed bug with lost contexts when reinstalling drivers. + if (FAILED(result)) + { + mRenderer->notifyDeviceLost(); + return EGL_CONTEXT_LOST; + } + + return EGL_SUCCESS; +} + +// Increments refcount on surface. +// caller must Release() the returned surface +IDirect3DSurface9 *SwapChain9::getRenderTarget() +{ + if (mRenderTarget) + { + mRenderTarget->AddRef(); + } + + return mRenderTarget; +} + +// Increments refcount on surface. +// caller must Release() the returned surface +IDirect3DSurface9 *SwapChain9::getDepthStencil() +{ + if (mDepthStencil) + { + mDepthStencil->AddRef(); + } + + return mDepthStencil; +} + +// Increments refcount on texture. +// caller must Release() the returned texture +IDirect3DTexture9 *SwapChain9::getOffscreenTexture() +{ + if (mOffscreenTexture) + { + mOffscreenTexture->AddRef(); + } + + return mOffscreenTexture; +} + +SwapChain9 *SwapChain9::makeSwapChain9(SwapChain *swapChain) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain9*, swapChain)); + return static_cast(swapChain); +} + +void SwapChain9::recreate() +{ + if (!mSwapChain) + { + return; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + if (device == NULL) + { + return; + } + + D3DPRESENT_PARAMETERS presentParameters; + HRESULT result = mSwapChain->GetPresentParameters(&presentParameters); + ASSERT(SUCCEEDED(result)); + + IDirect3DSwapChain9* newSwapChain = NULL; + result = device->CreateAdditionalSwapChain(&presentParameters, &newSwapChain); + if (FAILED(result)) + { + return; + } + + mSwapChain->Release(); + mSwapChain = newSwapChain; + + mBackBuffer->Release(); + result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); + ASSERT(SUCCEEDED(result)); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.h new file mode 100644 index 0000000000..16a62bd86f --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.h @@ -0,0 +1,55 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChain9.h: Defines a back-end specific class for the D3D9 swap chain. + +#ifndef LIBGLESV2_RENDERER_SWAPCHAIN9_H_ +#define LIBGLESV2_RENDERER_SWAPCHAIN9_H_ + +#include "common/angleutils.h" +#include "libGLESv2/renderer/SwapChain.h" + +namespace rx +{ +class Renderer9; + +class SwapChain9 : public SwapChain +{ + public: + SwapChain9(Renderer9 *renderer, HWND window, HANDLE shareHandle, + GLenum backBufferFormat, GLenum depthBufferFormat); + virtual ~SwapChain9(); + + EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); + virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); + virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); + virtual void recreate(); + + virtual IDirect3DSurface9 *getRenderTarget(); + virtual IDirect3DSurface9 *getDepthStencil(); + virtual IDirect3DTexture9 *getOffscreenTexture(); + + static SwapChain9 *makeSwapChain9(SwapChain *swapChain); + + private: + DISALLOW_COPY_AND_ASSIGN(SwapChain9); + + void release(); + + Renderer9 *mRenderer; + EGLint mHeight; + EGLint mWidth; + EGLint mSwapInterval; + + IDirect3DSwapChain9 *mSwapChain; + IDirect3DSurface9 *mBackBuffer; + IDirect3DSurface9 *mRenderTarget; + IDirect3DSurface9 *mDepthStencil; + IDirect3DTexture9* mOffscreenTexture; +}; + +} +#endif // LIBGLESV2_RENDERER_SWAPCHAIN9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp new file mode 100644 index 0000000000..2486a9a5bf --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp @@ -0,0 +1,328 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureStorage9.cpp: Implements the abstract rx::TextureStorage9 class and its concrete derived +// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the +// D3D9 texture. + +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d9/TextureStorage9.h" +#include "libGLESv2/renderer/d3d9/SwapChain9.h" +#include "libGLESv2/renderer/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" +#include "libGLESv2/Texture.h" + +namespace rx +{ +TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage) + : mLodOffset(0), + mRenderer(Renderer9::makeRenderer9(renderer)), + mD3DUsage(usage), + mD3DPool(mRenderer->getTexturePool(usage)) +{ +} + +TextureStorage9::~TextureStorage9() +{ +} + +TextureStorage9 *TextureStorage9::makeTextureStorage9(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9*, storage)); + return static_cast(storage); +} + +DWORD TextureStorage9::GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable) +{ + DWORD d3dusage = 0; + + if (d3dfmt == D3DFMT_INTZ) + { + d3dusage |= D3DUSAGE_DEPTHSTENCIL; + } + else if(forceRenderable || (TextureStorage9::IsTextureFormatRenderable(d3dfmt) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE))) + { + d3dusage |= D3DUSAGE_RENDERTARGET; + } + return d3dusage; +} + +bool TextureStorage9::IsTextureFormatRenderable(D3DFORMAT format) +{ + if (format == D3DFMT_INTZ) + { + return true; + } + switch(format) + { + case D3DFMT_L8: + case D3DFMT_A8L8: + case D3DFMT_DXT1: + case D3DFMT_DXT3: + case D3DFMT_DXT5: + return false; + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + case D3DFMT_A16B16G16R16F: + case D3DFMT_A32B32G32R32F: + return true; + default: + UNREACHABLE(); + } + + return false; +} + +bool TextureStorage9::isRenderTarget() const +{ + return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0; +} + +bool TextureStorage9::isManaged() const +{ + return (mD3DPool == D3DPOOL_MANAGED); +} + +D3DPOOL TextureStorage9::getPool() const +{ + return mD3DPool; +} + +DWORD TextureStorage9::getUsage() const +{ + return mD3DUsage; +} + +int TextureStorage9::getLodOffset() const +{ + return mLodOffset; +} + +int TextureStorage9::levelCount() +{ + return getBaseTexture() ? getBaseTexture()->GetLevelCount() - getLodOffset() : 0; +} + +TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain) : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET) +{ + IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture(); + mTexture = surfaceTexture; + mRenderTarget = NULL; + + initializeRenderTarget(); +} + +TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) + : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable)) +{ + mTexture = NULL; + mRenderTarget = NULL; + // if the width or height is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (width > 0 && height > 0) + { + IDirect3DDevice9 *device = mRenderer->getDevice(); + gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset); + HRESULT result = device->CreateTexture(width, height, levels ? levels + mLodOffset : 0, getUsage(), + mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + gl::error(GL_OUT_OF_MEMORY); + } + } + + initializeRenderTarget(); +} + +TextureStorage9_2D::~TextureStorage9_2D() +{ + if (mTexture) + { + mTexture->Release(); + } + + delete mRenderTarget; +} + +TextureStorage9_2D *TextureStorage9_2D::makeTextureStorage9_2D(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_2D*, storage)); + return static_cast(storage); +} + +// Increments refcount on surface. +// caller must Release() the returned surface +IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty) +{ + IDirect3DSurface9 *surface = NULL; + + if (mTexture) + { + HRESULT result = mTexture->GetSurfaceLevel(level + mLodOffset, &surface); + ASSERT(SUCCEEDED(result)); + + // With managed textures the driver needs to be informed of updates to the lower mipmap levels + if (level + mLodOffset != 0 && isManaged() && dirty) + { + mTexture->AddDirtyRect(NULL); + } + } + + return surface; +} + +RenderTarget *TextureStorage9_2D::getRenderTarget() +{ + return mRenderTarget; +} + +void TextureStorage9_2D::generateMipmap(int level) +{ + IDirect3DSurface9 *upper = getSurfaceLevel(level - 1, false); + IDirect3DSurface9 *lower = getSurfaceLevel(level, true); + + if (upper != NULL && lower != NULL) + { + mRenderer->boxFilter(upper, lower); + } + + if (upper != NULL) upper->Release(); + if (lower != NULL) lower->Release(); +} + +IDirect3DBaseTexture9 *TextureStorage9_2D::getBaseTexture() const +{ + return mTexture; +} + +void TextureStorage9_2D::initializeRenderTarget() +{ + ASSERT(mRenderTarget == NULL); + + if (mTexture != NULL && isRenderTarget()) + { + IDirect3DSurface9 *surface = getSurfaceLevel(0, false); + + mRenderTarget = new RenderTarget9(mRenderer, surface); + } +} + +TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) + : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable)) +{ + mTexture = NULL; + for (int i = 0; i < 6; ++i) + { + mRenderTarget[i] = NULL; + } + + // if the size is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (size > 0) + { + IDirect3DDevice9 *device = mRenderer->getDevice(); + int height = size; + gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset); + HRESULT result = device->CreateCubeTexture(size, levels ? levels + mLodOffset : 0, getUsage(), + mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + gl::error(GL_OUT_OF_MEMORY); + } + } + + initializeRenderTarget(); +} + +TextureStorage9_Cube::~TextureStorage9_Cube() +{ + if (mTexture) + { + mTexture->Release(); + } + + for (int i = 0; i < 6; ++i) + { + delete mRenderTarget[i]; + } +} + +TextureStorage9_Cube *TextureStorage9_Cube::makeTextureStorage9_Cube(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_Cube*, storage)); + return static_cast(storage); +} + +// Increments refcount on surface. +// caller must Release() the returned surface +IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty) +{ + IDirect3DSurface9 *surface = NULL; + + if (mTexture) + { + D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget); + HRESULT result = mTexture->GetCubeMapSurface(face, level + mLodOffset, &surface); + ASSERT(SUCCEEDED(result)); + + // With managed textures the driver needs to be informed of updates to the lower mipmap levels + if (level != 0 && isManaged() && dirty) + { + mTexture->AddDirtyRect(face, NULL); + } + } + + return surface; +} + +RenderTarget *TextureStorage9_Cube::getRenderTarget(GLenum faceTarget) +{ + return mRenderTarget[gl::TextureCubeMap::faceIndex(faceTarget)]; +} + +void TextureStorage9_Cube::generateMipmap(int face, int level) +{ + IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1, false); + IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true); + + if (upper != NULL && lower != NULL) + { + mRenderer->boxFilter(upper, lower); + } + + if (upper != NULL) upper->Release(); + if (lower != NULL) lower->Release(); +} + +IDirect3DBaseTexture9 *TextureStorage9_Cube::getBaseTexture() const +{ + return mTexture; +} + +void TextureStorage9_Cube::initializeRenderTarget() +{ + if (mTexture != NULL && isRenderTarget()) + { + IDirect3DSurface9 *surface = NULL; + + for (int i = 0; i < 6; ++i) + { + ASSERT(mRenderTarget[i] == NULL); + + surface = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, false); + + mRenderTarget[i] = new RenderTarget9(mRenderer, surface); + } + } +} + +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h new file mode 100644 index 0000000000..86f551a131 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h @@ -0,0 +1,109 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureStorage9.h: Defines the abstract rx::TextureStorage9 class and its concrete derived +// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the +// D3D9 texture. + +#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ +#define LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ + +#include "libGLESv2/renderer/TextureStorage.h" +#include "common/debug.h" + +namespace rx +{ +class Renderer9; +class SwapChain9; +class RenderTarget; +class RenderTarget9; +class Blit; + +class TextureStorage9 : public TextureStorage +{ + public: + TextureStorage9(Renderer *renderer, DWORD usage); + virtual ~TextureStorage9(); + + static TextureStorage9 *makeTextureStorage9(TextureStorage *storage); + + static DWORD GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable); + static bool IsTextureFormatRenderable(D3DFORMAT format); + + D3DPOOL getPool() const; + DWORD getUsage() const; + + virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0; + virtual RenderTarget *getRenderTarget() { return NULL; } + virtual RenderTarget *getRenderTarget(GLenum faceTarget) { return NULL; } + virtual void generateMipmap(int level) {}; + virtual void generateMipmap(int face, int level) {}; + + virtual int getLodOffset() const; + virtual bool isRenderTarget() const; + virtual bool isManaged() const; + virtual int levelCount(); + + protected: + int mLodOffset; + Renderer9 *mRenderer; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage9); + + const DWORD mD3DUsage; + const D3DPOOL mD3DPool; +}; + +class TextureStorage9_2D : public TextureStorage9 +{ + public: + TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain); + TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); + virtual ~TextureStorage9_2D(); + + static TextureStorage9_2D *makeTextureStorage9_2D(TextureStorage *storage); + + IDirect3DSurface9 *getSurfaceLevel(int level, bool dirty); + virtual RenderTarget *getRenderTarget(); + virtual IDirect3DBaseTexture9 *getBaseTexture() const; + virtual void generateMipmap(int level); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage9_2D); + + void initializeRenderTarget(); + + IDirect3DTexture9 *mTexture; + RenderTarget9 *mRenderTarget; +}; + +class TextureStorage9_Cube : public TextureStorage9 +{ + public: + TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); + virtual ~TextureStorage9_Cube(); + + static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage); + + IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level, bool dirty); + virtual RenderTarget *getRenderTarget(GLenum faceTarget); + virtual IDirect3DBaseTexture9 *getBaseTexture() const; + virtual void generateMipmap(int face, int level); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage9_Cube); + + void initializeRenderTarget(); + + IDirect3DCubeTexture9 *mTexture; + RenderTarget9 *mRenderTarget[6]; +}; + +} + +#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ + diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp new file mode 100644 index 0000000000..57f5bcd256 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp @@ -0,0 +1,530 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation. + +#include "libGLESv2/renderer/d3d9/VertexBuffer9.h" +#include "libGLESv2/renderer/d3d9/vertexconversion.h" +#include "libGLESv2/renderer/BufferStorage.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" + +#include "libGLESv2/Buffer.h" + +namespace rx +{ + +bool VertexBuffer9::mTranslationsInitialized = false; +VertexBuffer9::FormatConverter VertexBuffer9::mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; + +VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer) +{ + mVertexBuffer = NULL; + mBufferSize = 0; + mDynamicUsage = false; + + if (!mTranslationsInitialized) + { + initializeTranslations(renderer->getCapsDeclTypes()); + mTranslationsInitialized = true; + } +} + +VertexBuffer9::~VertexBuffer9() +{ + if (mVertexBuffer) + { + mVertexBuffer->Release(); + mVertexBuffer = NULL; + } +} + +bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) +{ + if (mVertexBuffer) + { + mVertexBuffer->Release(); + mVertexBuffer = NULL; + } + + updateSerial(); + + if (size > 0) + { + DWORD flags = D3DUSAGE_WRITEONLY; + if (dynamicUsage) + { + flags |= D3DUSAGE_DYNAMIC; + } + + HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer); + + if (FAILED(result)) + { + ERR("Out of memory allocating a vertex buffer of size %lu.", size); + return false; + } + } + + mBufferSize = size; + mDynamicUsage = dynamicUsage; + return true; +} + +VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer)); + return static_cast(vertexBuffer); +} + +bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, + GLsizei instances, unsigned int offset) +{ + if (mVertexBuffer) + { + gl::Buffer *buffer = attrib.mBoundBuffer.get(); + + int inputStride = attrib.stride(); + int elementSize = attrib.typeSize(); + const FormatConverter &converter = formatConverter(attrib); + + DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; + + void *mapPtr = NULL; + + unsigned int mapSize; + if (!spaceRequired(attrib, count, instances, &mapSize)) + { + return false; + } + + HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags); + + if (FAILED(result)) + { + ERR("Lock failed with error 0x%08x", result); + return false; + } + + const char *input = NULL; + if (buffer) + { + BufferStorage *storage = buffer->getStorage(); + input = static_cast(storage->getData()) + static_cast(attrib.mOffset); + } + else + { + input = static_cast(attrib.mPointer); + } + + if (instances == 0 || attrib.mDivisor == 0) + { + input += inputStride * start; + } + + if (converter.identity && inputStride == elementSize) + { + memcpy(mapPtr, input, count * inputStride); + } + else + { + converter.convertArray(input, inputStride, count, mapPtr); + } + + mVertexBuffer->Unlock(); + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +bool VertexBuffer9::storeRawData(const void* data, unsigned int size, unsigned int offset) +{ + if (mVertexBuffer) + { + DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; + + void *mapPtr = NULL; + HRESULT result = mVertexBuffer->Lock(offset, size, &mapPtr, lockFlags); + + if (FAILED(result)) + { + ERR("Lock failed with error 0x%08x", result); + return false; + } + + memcpy(mapPtr, data, size); + + mVertexBuffer->Unlock(); + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, + unsigned int *outSpaceRequired) const +{ + return spaceRequired(attrib, count, instances, outSpaceRequired); +} + +bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const +{ + return !formatConverter(attrib).identity; +} + +unsigned int VertexBuffer9::getVertexSize(const gl::VertexAttribute &attrib) const +{ + unsigned int spaceRequired; + return getSpaceRequired(attrib, 1, 0, &spaceRequired) ? spaceRequired : 0; +} + +D3DDECLTYPE VertexBuffer9::getDeclType(const gl::VertexAttribute &attrib) const +{ + return formatConverter(attrib).d3dDeclType; +} + +unsigned int VertexBuffer9::getBufferSize() const +{ + return mBufferSize; +} + +bool VertexBuffer9::setBufferSize(unsigned int size) +{ + if (size > mBufferSize) + { + return initialize(size, mDynamicUsage); + } + else + { + return true; + } +} + +bool VertexBuffer9::discard() +{ + if (mVertexBuffer) + { + void *dummy; + HRESULT result; + + result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); + if (FAILED(result)) + { + ERR("Discard lock failed with error 0x%08x", result); + return false; + } + + result = mVertexBuffer->Unlock(); + if (FAILED(result)) + { + ERR("Discard unlock failed with error 0x%08x", result); + return false; + } + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const +{ + return mVertexBuffer; +} + +// 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 : NoWiden { }; +template struct WidenRule : WidenToEven { }; +template struct WidenRule : WidenToEven { }; +template struct WidenRule : WidenToFour { }; +template struct WidenRule : WidenToFour { }; +template struct WidenRule : 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 : Cast::type, typename D3DToCType::type> { }; + +// All conversions from normalized types to float use the Normalize operator. +template struct ConversionRule : Normalize::type> { }; + +// Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules. +template <> struct ConversionRule : FixedToFloat { }; +template <> struct ConversionRule : 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 : NormalizedDefaultValues { }; +template struct DefaultVertexValuesStage2 : SimpleDefaultValues { }; + +// Work out the default value rule for a D3D type (expressed as the C type) and +template struct DefaultVertexValues : DefaultVertexValuesStage2 { }; +template struct DefaultVertexValues : 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 + : 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 }; +}; + +// Initialize 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) }, \ + } + +#define TRANSLATIONS_FOR_TYPE_NO_NORM(type) \ + { \ + { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ + { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ + } + +const VertexBuffer9::TranslationDescription VertexBuffer9::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1] +{ + TRANSLATIONS_FOR_TYPE(GL_BYTE), + TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE), + TRANSLATIONS_FOR_TYPE(GL_SHORT), + TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT), + TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED), + TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT) +}; + +void VertexBuffer9::initializeTranslations(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) + { + mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion; + } + else + { + mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion; + } + } + } + } +} + +unsigned int VertexBuffer9::typeIndex(GLenum type) +{ + 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; + } +} + +const VertexBuffer9::FormatConverter &VertexBuffer9::formatConverter(const gl::VertexAttribute &attribute) +{ + return mFormatConverters[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1]; +} + +bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, + unsigned int *outSpaceRequired) +{ + unsigned int elementSize = formatConverter(attrib).outputElementSize; + + if (attrib.mArrayEnabled) + { + unsigned int elementCount = 0; + if (instances == 0 || attrib.mDivisor == 0) + { + elementCount = count; + } + else + { + if (static_cast(instances) < std::numeric_limits::max() - (attrib.mDivisor - 1)) + { + // Round up + elementCount = (static_cast(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor; + } + else + { + elementCount = static_cast(instances) / attrib.mDivisor; + } + } + + if (elementSize <= std::numeric_limits::max() / elementCount) + { + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * elementCount; + } + return true; + } + else + { + return false; + } + } + else + { + const unsigned int elementSize = 4; + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * 4; + } + return true; + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h new file mode 100644 index 0000000000..2f88117bda --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h @@ -0,0 +1,91 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexBuffer9.h: Defines the D3D9 VertexBuffer implementation. + +#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ +#define LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ + +#include "libGLESv2/renderer/VertexBuffer.h" + +namespace rx +{ +class Renderer9; + +class VertexBuffer9 : public VertexBuffer +{ + public: + explicit VertexBuffer9(rx::Renderer9 *const renderer); + virtual ~VertexBuffer9(); + + virtual bool initialize(unsigned int size, bool dynamicUsage); + + static VertexBuffer9 *makeVertexBuffer9(VertexBuffer *vertexBuffer); + + virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, + unsigned int offset); + virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset); + + virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const; + + virtual bool requiresConversion(const gl::VertexAttribute &attrib) const; + + unsigned int getVertexSize(const gl::VertexAttribute &attrib) const; + D3DDECLTYPE getDeclType(const gl::VertexAttribute &attrib) const; + + virtual unsigned int getBufferSize() const; + virtual bool setBufferSize(unsigned int size); + virtual bool discard(); + + IDirect3DVertexBuffer9 *getBuffer() const; + + private: + DISALLOW_COPY_AND_ASSIGN(VertexBuffer9); + + rx::Renderer9 *const mRenderer; + + IDirect3DVertexBuffer9 *mVertexBuffer; + unsigned int mBufferSize; + bool mDynamicUsage; + + // Attribute format conversion + enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; + + 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; + }; + + static bool mTranslationsInitialized; + static void initializeTranslations(DWORD declTypes); + + // [GL types as enumerated by typeIndex()][normalized][size - 1] + static FormatConverter mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; + + struct TranslationDescription + { + DWORD capsFlag; + FormatConverter preferredConversion; + FormatConverter fallbackConversion; + }; + + // This table is used to generate mFormatConverters. + // [GL types as enumerated by typeIndex()][normalized][size - 1] + static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; + + static unsigned int typeIndex(GLenum type); + static const FormatConverter &formatConverter(const gl::VertexAttribute &attribute); + + static bool spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, + unsigned int *outSpaceRequired); +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp new file mode 100644 index 0000000000..e5c8a14232 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp @@ -0,0 +1,217 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations. + +#include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/renderer/d3d9/VertexBuffer9.h" +#include "libGLESv2/renderer/d3d9/VertexDeclarationCache.h" + +namespace rx +{ + +VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0) +{ + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + mVertexDeclCache[i].vertexDeclaration = NULL; + mVertexDeclCache[i].lruCount = 0; + } + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mAppliedVBs[i].serial = 0; + } + + mLastSetVDecl = NULL; + mInstancingEnabled = true; +} + +VertexDeclarationCache::~VertexDeclarationCache() +{ + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + if (mVertexDeclCache[i].vertexDeclaration) + { + mVertexDeclCache[i].vertexDeclaration->Release(); + } + } +} + +GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw) +{ + *repeatDraw = 1; + + int indexedAttribute = gl::MAX_VERTEX_ATTRIBS; + int instancedAttribute = gl::MAX_VERTEX_ATTRIBS; + + if (instances > 0) + { + // Find an indexed attribute to be mapped to D3D stream 0 + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (attributes[i].active) + { + if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor == 0) + { + indexedAttribute = i; + } + else if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor != 0) + { + instancedAttribute = i; + } + if (indexedAttribute != gl::MAX_VERTEX_ATTRIBS && instancedAttribute != gl::MAX_VERTEX_ATTRIBS) + break; // Found both an indexed and instanced attribute + } + } + + if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS) + { + return GL_INVALID_OPERATION; + } + } + + D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1]; + D3DVERTEXELEMENT9 *element = &elements[0]; + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (attributes[i].active) + { + // Directly binding the storage buffer is not supported for d3d9 + ASSERT(attributes[i].storage == NULL); + + int stream = i; + + if (instances > 0) + { + // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced. + if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS) + { + *repeatDraw = instances; + } + else + { + if (i == indexedAttribute) + { + stream = 0; + } + else if (i == 0) + { + stream = indexedAttribute; + } + + UINT frequency = 1; + + if (attributes[i].divisor == 0) + { + frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances; + } + else + { + frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor; + } + + device->SetStreamSourceFreq(stream, frequency); + mInstancingEnabled = true; + } + } + + VertexBuffer9 *vertexBuffer = VertexBuffer9::makeVertexBuffer9(attributes[i].vertexBuffer); + + if (mAppliedVBs[stream].serial != attributes[i].serial || + mAppliedVBs[stream].stride != attributes[i].stride || + mAppliedVBs[stream].offset != attributes[i].offset) + { + device->SetStreamSource(stream, vertexBuffer->getBuffer(), attributes[i].offset, attributes[i].stride); + mAppliedVBs[stream].serial = attributes[i].serial; + mAppliedVBs[stream].stride = attributes[i].stride; + mAppliedVBs[stream].offset = attributes[i].offset; + } + + element->Stream = stream; + element->Offset = 0; + element->Type = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDeclType(*attributes[i].attribute) : D3DDECLTYPE_FLOAT4; + element->Method = D3DDECLMETHOD_DEFAULT; + element->Usage = D3DDECLUSAGE_TEXCOORD; + element->UsageIndex = programBinary->getSemanticIndex(i); + element++; + } + } + + if (instances == 0 || instancedAttribute == gl::MAX_VERTEX_ATTRIBS) + { + if (mInstancingEnabled) + { + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + device->SetStreamSourceFreq(i, 1); + } + + mInstancingEnabled = false; + } + } + + static const D3DVERTEXELEMENT9 end = D3DDECL_END(); + *(element++) = end; + + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + VertexDeclCacheEntry *entry = &mVertexDeclCache[i]; + if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration) + { + entry->lruCount = ++mMaxLru; + if(entry->vertexDeclaration != mLastSetVDecl) + { + device->SetVertexDeclaration(entry->vertexDeclaration); + mLastSetVDecl = entry->vertexDeclaration; + } + + return GL_NO_ERROR; + } + } + + VertexDeclCacheEntry *lastCache = mVertexDeclCache; + + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + if (mVertexDeclCache[i].lruCount < lastCache->lruCount) + { + lastCache = &mVertexDeclCache[i]; + } + } + + if (lastCache->vertexDeclaration != NULL) + { + lastCache->vertexDeclaration->Release(); + lastCache->vertexDeclaration = NULL; + // mLastSetVDecl is set to the replacement, so we don't have to worry + // about it. + } + + memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)); + device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration); + device->SetVertexDeclaration(lastCache->vertexDeclaration); + mLastSetVDecl = lastCache->vertexDeclaration; + lastCache->lruCount = ++mMaxLru; + + return GL_NO_ERROR; +} + +void VertexDeclarationCache::markStateDirty() +{ + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mAppliedVBs[i].serial = 0; + } + + mLastSetVDecl = NULL; + mInstancingEnabled = true; // Forces it to be disabled when not used +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h new file mode 100644 index 0000000000..3fc024a9ba --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h @@ -0,0 +1,58 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexDeclarationCache.h: Defines a helper class to construct and cache vertex declarations. + +#ifndef LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ +#define LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ + +#include "libGLESv2/renderer/VertexDataManager.h" + +namespace gl +{ +class VertexDataManager; +} + +namespace rx +{ + +class VertexDeclarationCache +{ + public: + VertexDeclarationCache(); + ~VertexDeclarationCache(); + + GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw); + + void markStateDirty(); + + private: + UINT mMaxLru; + + enum { NUM_VERTEX_DECL_CACHE_ENTRIES = 32 }; + + struct VBData + { + unsigned int serial; + unsigned int stride; + unsigned int offset; + }; + + VBData mAppliedVBs[gl::MAX_VERTEX_ATTRIBS]; + IDirect3DVertexDeclaration9 *mLastSetVDecl; + bool mInstancingEnabled; + + struct VertexDeclCacheEntry + { + D3DVERTEXELEMENT9 cachedElements[gl::MAX_VERTEX_ATTRIBS + 1]; + UINT lruCount; + IDirect3DVertexDeclaration9 *vertexDeclaration; + } mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES]; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp new file mode 100644 index 0000000000..b7f2ffb1d9 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp @@ -0,0 +1,500 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// renderer9_utils.cpp: Conversion functions and other utility routines +// specific to the D3D9 renderer. + +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" +#include "libGLESv2/mathutil.h" +#include "libGLESv2/Context.h" + +#include "common/debug.h" + +namespace gl_d3d9 +{ + +D3DCMPFUNC ConvertComparison(GLenum comparison) +{ + D3DCMPFUNC d3dComp = D3DCMP_ALWAYS; + switch (comparison) + { + case GL_NEVER: d3dComp = D3DCMP_NEVER; break; + case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break; + case GL_LESS: d3dComp = D3DCMP_LESS; break; + case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break; + case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break; + case GL_GREATER: d3dComp = D3DCMP_GREATER; break; + case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break; + case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break; + default: UNREACHABLE(); + } + + return d3dComp; +} + +D3DCOLOR ConvertColor(gl::Color color) +{ + return D3DCOLOR_RGBA(gl::unorm<8>(color.red), + gl::unorm<8>(color.green), + gl::unorm<8>(color.blue), + gl::unorm<8>(color.alpha)); +} + +D3DBLEND ConvertBlendFunc(GLenum blend) +{ + D3DBLEND d3dBlend = D3DBLEND_ZERO; + + switch (blend) + { + case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break; + case GL_ONE: d3dBlend = D3DBLEND_ONE; break; + case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break; + case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break; + case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break; + case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break; + case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break; + case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break; + case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break; + case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break; + case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; + case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break; + case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; + case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break; + default: UNREACHABLE(); + } + + return d3dBlend; +} + +D3DBLENDOP ConvertBlendOp(GLenum blendOp) +{ + D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD; + + switch (blendOp) + { + case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break; + case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break; + case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break; + default: UNREACHABLE(); + } + + return d3dBlendOp; +} + +D3DSTENCILOP ConvertStencilOp(GLenum stencilOp) +{ + D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP; + + switch (stencilOp) + { + case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break; + case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break; + case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break; + case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break; + case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break; + case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break; + case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break; + case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break; + default: UNREACHABLE(); + } + + return d3dStencilOp; +} + +D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap) +{ + D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP; + + switch (wrap) + { + case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break; + case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break; + case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break; + default: UNREACHABLE(); + } + + return d3dWrap; +} + +D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace) +{ + D3DCULL cull = D3DCULL_CCW; + switch (cullFace) + { + case GL_FRONT: + cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW); + break; + case GL_BACK: + cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW); + break; + case GL_FRONT_AND_BACK: + cull = D3DCULL_NONE; // culling will be handled during draw + break; + default: UNREACHABLE(); + } + + return cull; +} + +D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace) +{ + D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X; + + switch (cubeFace) + { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + face = D3DCUBEMAP_FACE_POSITIVE_X; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + face = D3DCUBEMAP_FACE_NEGATIVE_X; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + face = D3DCUBEMAP_FACE_POSITIVE_Y; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + face = D3DCUBEMAP_FACE_NEGATIVE_Y; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + face = D3DCUBEMAP_FACE_POSITIVE_Z; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + face = D3DCUBEMAP_FACE_NEGATIVE_Z; + break; + default: UNREACHABLE(); + } + + return face; +} + +DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha) +{ + return (red ? D3DCOLORWRITEENABLE_RED : 0) | + (green ? D3DCOLORWRITEENABLE_GREEN : 0) | + (blue ? D3DCOLORWRITEENABLE_BLUE : 0) | + (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0); +} + +D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy) +{ + if (maxAnisotropy > 1.0f) + { + return D3DTEXF_ANISOTROPIC; + } + + D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT; + switch (magFilter) + { + case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break; + case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break; + default: UNREACHABLE(); + } + + return d3dMagFilter; +} + +void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy) +{ + switch (minFilter) + { + case GL_NEAREST: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_NONE; + break; + case GL_LINEAR: + *d3dMinFilter = D3DTEXF_LINEAR; + *d3dMipFilter = D3DTEXF_NONE; + break; + case GL_NEAREST_MIPMAP_NEAREST: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_POINT; + break; + case GL_LINEAR_MIPMAP_NEAREST: + *d3dMinFilter = D3DTEXF_LINEAR; + *d3dMipFilter = D3DTEXF_POINT; + break; + case GL_NEAREST_MIPMAP_LINEAR: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_LINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + *d3dMinFilter = D3DTEXF_LINEAR; + *d3dMipFilter = D3DTEXF_LINEAR; + break; + default: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_NONE; + UNREACHABLE(); + } + + if (maxAnisotropy > 1.0f) + { + *d3dMinFilter = D3DTEXF_ANISOTROPIC; + } +} + +D3DFORMAT ConvertRenderbufferFormat(GLenum format) +{ + switch (format) + { + case GL_NONE: return D3DFMT_NULL; + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8_OES: return D3DFMT_A8R8G8B8; + case GL_RGB565: return D3DFMT_R5G6B5; + case GL_RGB8_OES: return D3DFMT_X8R8G8B8; + case GL_DEPTH_COMPONENT16: + case GL_STENCIL_INDEX8: + case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8; + default: UNREACHABLE(); return D3DFMT_A8R8G8B8; + } +} + +D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples) +{ + if (samples <= 1) + return D3DMULTISAMPLE_NONE; + else + return (D3DMULTISAMPLE_TYPE)samples; +} + +} + +namespace d3d9_gl +{ + +unsigned int GetStencilSize(D3DFORMAT stencilFormat) +{ + if (stencilFormat == D3DFMT_INTZ) + { + return 8; + } + switch(stencilFormat) + { + case D3DFMT_D24FS8: + case D3DFMT_D24S8: + return 8; + case D3DFMT_D24X4S4: + return 4; + case D3DFMT_D15S1: + return 1; + case D3DFMT_D16_LOCKABLE: + case D3DFMT_D32: + case D3DFMT_D24X8: + case D3DFMT_D32F_LOCKABLE: + case D3DFMT_D16: + return 0; + //case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only + //case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only + default: + return 0; + } +} + +unsigned int GetAlphaSize(D3DFORMAT colorFormat) +{ + switch (colorFormat) + { + case D3DFMT_A16B16G16R16F: + return 16; + case D3DFMT_A32B32G32R32F: + return 32; + case D3DFMT_A2R10G10B10: + return 2; + case D3DFMT_A8R8G8B8: + return 8; + case D3DFMT_A1R5G5B5: + return 1; + case D3DFMT_X8R8G8B8: + case D3DFMT_R5G6B5: + return 0; + default: + return 0; + } +} + +GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type) +{ + if (type == D3DMULTISAMPLE_NONMASKABLE) + return 0; + else + return type; +} + +bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format) +{ + switch (d3dformat) + { + case D3DFMT_L8: + return (format == GL_LUMINANCE); + case D3DFMT_A8L8: + return (format == GL_LUMINANCE_ALPHA); + case D3DFMT_DXT1: + return (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT); + case D3DFMT_DXT3: + return (format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); + case D3DFMT_DXT5: + return (format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); + case D3DFMT_A8R8G8B8: + case D3DFMT_A16B16G16R16F: + case D3DFMT_A32B32G32R32F: + return (format == GL_RGBA || format == GL_BGRA_EXT); + case D3DFMT_X8R8G8B8: + return (format == GL_RGB); + default: + if (d3dformat == D3DFMT_INTZ && gl::IsDepthTexture(format)) + return true; + return false; + } +} + +GLenum ConvertBackBufferFormat(D3DFORMAT format) +{ + switch (format) + { + case D3DFMT_A4R4G4B4: return GL_RGBA4; + case D3DFMT_A8R8G8B8: return GL_RGBA8_OES; + case D3DFMT_A1R5G5B5: return GL_RGB5_A1; + case D3DFMT_R5G6B5: return GL_RGB565; + case D3DFMT_X8R8G8B8: return GL_RGB8_OES; + default: + UNREACHABLE(); + } + + return GL_RGBA4; +} + +GLenum ConvertDepthStencilFormat(D3DFORMAT format) +{ + if (format == D3DFMT_INTZ) + { + return GL_DEPTH24_STENCIL8_OES; + } + switch (format) + { + case D3DFMT_D16: + case D3DFMT_D24X8: + return GL_DEPTH_COMPONENT16; + case D3DFMT_D24S8: + return GL_DEPTH24_STENCIL8_OES; + case D3DFMT_UNKNOWN: + return GL_NONE; + default: + UNREACHABLE(); + } + + return GL_DEPTH24_STENCIL8_OES; +} + +GLenum ConvertRenderTargetFormat(D3DFORMAT format) +{ + if (format == D3DFMT_INTZ) + { + return GL_DEPTH24_STENCIL8_OES; + } + + 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; + case D3DFMT_D16: + case D3DFMT_D24X8: + return GL_DEPTH_COMPONENT16; + case D3DFMT_D24S8: + return GL_DEPTH24_STENCIL8_OES; + case D3DFMT_UNKNOWN: + return GL_NONE; + default: + UNREACHABLE(); + } + + return GL_RGBA4; +} + +GLenum GetEquivalentFormat(D3DFORMAT format) +{ + if (format == D3DFMT_INTZ) + return GL_DEPTH24_STENCIL8_OES; + if (format == D3DFMT_NULL) + return GL_NONE; + + 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; + case D3DFMT_D16: return GL_DEPTH_COMPONENT16; + case D3DFMT_D24S8: return GL_DEPTH24_STENCIL8_OES; + case D3DFMT_UNKNOWN: return GL_NONE; + case D3DFMT_DXT1: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + case D3DFMT_DXT3: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE; + case D3DFMT_DXT5: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE; + case D3DFMT_A32B32G32R32F: return GL_RGBA32F_EXT; + case D3DFMT_A16B16G16R16F: return GL_RGBA16F_EXT; + case D3DFMT_L8: return GL_LUMINANCE8_EXT; + case D3DFMT_A8L8: return GL_LUMINANCE8_ALPHA8_EXT; + default: UNREACHABLE(); + return GL_NONE; + } +} + +} + +namespace d3d9 +{ + +bool IsCompressedFormat(D3DFORMAT surfaceFormat) +{ + switch(surfaceFormat) + { + case D3DFMT_DXT1: + case D3DFMT_DXT2: + case D3DFMT_DXT3: + case D3DFMT_DXT4: + case D3DFMT_DXT5: + return true; + default: + return false; + } +} + +size_t ComputeRowSize(D3DFORMAT format, unsigned int width) +{ + if (format == D3DFMT_INTZ) + { + return 4 * width; + } + switch (format) + { + case D3DFMT_L8: + return 1 * width; + case D3DFMT_A8L8: + return 2 * width; + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + return 4 * width; + case D3DFMT_A16B16G16R16F: + return 8 * width; + case D3DFMT_A32B32G32R32F: + return 16 * width; + case D3DFMT_DXT1: + return 8 * ((width + 3) / 4); + case D3DFMT_DXT3: + case D3DFMT_DXT5: + return 16 * ((width + 3) / 4); + default: + UNREACHABLE(); + return 0; + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h new file mode 100644 index 0000000000..bf6cdf1ea6 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h @@ -0,0 +1,74 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// renderer9_utils.h: Conversion functions and other utility routines +// specific to the D3D9 renderer + +#ifndef LIBGLESV2_RENDERER_RENDERER9_UTILS_H +#define LIBGLESV2_RENDERER_RENDERER9_UTILS_H + +#include "libGLESv2/utilities.h" + +const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z'))); +const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L'))); + +namespace gl_d3d9 +{ + +D3DCMPFUNC ConvertComparison(GLenum comparison); +D3DCOLOR ConvertColor(gl::Color color); +D3DBLEND ConvertBlendFunc(GLenum blend); +D3DBLENDOP ConvertBlendOp(GLenum blendOp); +D3DSTENCILOP ConvertStencilOp(GLenum stencilOp); +D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap); +D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace); +D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace); +DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha); +D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy); +void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy); +D3DFORMAT ConvertRenderbufferFormat(GLenum format); +D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples); + +} + +namespace d3d9_gl +{ + +GLuint GetAlphaSize(D3DFORMAT colorFormat); +GLuint GetStencilSize(D3DFORMAT stencilFormat); + +GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type); + +bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format); +GLenum ConvertBackBufferFormat(D3DFORMAT format); +GLenum ConvertDepthStencilFormat(D3DFORMAT format); +GLenum ConvertRenderTargetFormat(D3DFORMAT format); +GLenum GetEquivalentFormat(D3DFORMAT format); + +} + +namespace d3d9 +{ +bool IsCompressedFormat(D3DFORMAT format); +size_t ComputeRowSize(D3DFORMAT format, unsigned int width); + +inline bool isDeviceLostError(HRESULT errorCode) +{ + switch (errorCode) + { + case D3DERR_DRIVERINTERNALERROR: + case D3DERR_DEVICELOST: + case D3DERR_DEVICEHUNG: + case D3DERR_DEVICEREMOVED: + return true; + default: + return false; + } +} + +} + +#endif // LIBGLESV2_RENDERER_RENDERER9_UTILS_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps new file mode 100644 index 0000000000..dcb3bd0e76 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps @@ -0,0 +1,39 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +sampler2D tex : s0; + +uniform float4 mode : c0; + +// Passthrough Pixel Shader +// Outputs texture 0 sampled at texcoord 0. +float4 passthroughps(float4 texcoord : TEXCOORD0) : COLOR +{ + return tex2D(tex, texcoord.xy); +}; + +// Luminance Conversion Pixel Shader +// Outputs sample(tex0, tc0).rrra. +// For LA output (pass A) set C0.X = 1, C0.Y = 0. +// For L output (A = 1) set C0.X = 0, C0.Y = 1. +float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR +{ + float4 tmp = tex2D(tex, texcoord.xy); + tmp.w = tmp.w * mode.x + mode.y; + return tmp.xxxw; +}; + +// RGB/A Component Mask Pixel Shader +// Outputs sample(tex0, tc0) with options to force RGB = 0 and/or A = 1. +// To force RGB = 0, set C0.X = 0, otherwise C0.X = 1. +// To force A = 1, set C0.Z = 0, C0.W = 1, otherwise C0.Z = 1, C0.W = 0. +float4 componentmaskps(float4 texcoord : TEXCOORD0) : COLOR +{ + float4 tmp = tex2D(tex, texcoord.xy); + tmp.xyz = tmp.xyz * mode.x; + tmp.w = tmp.w * mode.z + mode.w; + return tmp; +}; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.vs b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.vs new file mode 100644 index 0000000000..3a36980b93 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.vs @@ -0,0 +1,43 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +struct VS_OUTPUT +{ + float4 position : POSITION; + float4 texcoord : TEXCOORD0; +}; + +uniform float4 halfPixelSize : c0; + +// Standard Vertex Shader +// Input 0 is the homogenous position. +// Outputs the homogenous position as-is. +// Outputs a tex coord with (0,0) in the upper-left corner of the screen and (1,1) in the bottom right. +// C0.X must be negative half-pixel width, C0.Y must be half-pixel height. C0.ZW must be 0. +VS_OUTPUT standardvs(in float4 position : POSITION) +{ + VS_OUTPUT Out; + + Out.position = position + halfPixelSize; + Out.texcoord = position * float4(0.5, -0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0); + + return Out; +}; + +// Flip Y Vertex Shader +// Input 0 is the homogenous position. +// Outputs the homogenous position as-is. +// Outputs a tex coord with (0,1) in the upper-left corner of the screen and (1,0) in the bottom right. +// C0.XY must be the half-pixel width and height. C0.ZW must be 0. +VS_OUTPUT flipyvs(in float4 position : POSITION) +{ + VS_OUTPUT Out; + + Out.position = position + halfPixelSize; + Out.texcoord = position * float4(0.5, 0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0); + + return Out; +}; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/vertexconversion.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/vertexconversion.h new file mode 100644 index 0000000000..590b9d48a3 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/vertexconversion.h @@ -0,0 +1,203 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// vertexconversion.h: A library of vertex conversion classes that can be used to build +// the FormatConverter objects used by the buffer conversion system. + +#ifndef LIBGLESV2_VERTEXCONVERSION_H_ +#define LIBGLESV2_VERTEXCONVERSION_H_ + +namespace rx +{ + +// Conversion types: +// static const bool identity: true if this is an identity transform, false otherwise +// static U convert(T): convert a single element from the input type to the output type +// typedef ... OutputType: the type produced by this conversion + +template +struct Identity +{ + static const bool identity = true; + + typedef T OutputType; + + static T convert(T x) + { + return x; + } +}; + +template +struct Cast +{ + static const bool identity = false; + + typedef ToT OutputType; + + static ToT convert(FromT x) + { + return static_cast(x); + } +}; + +template +struct Cast +{ + static const bool identity = true; + + typedef T OutputType; + + static T convert(T x) + { + return static_cast(x); + } +}; + +template +struct Normalize +{ + static const bool identity = false; + + typedef float OutputType; + + static float convert(T x) + { + typedef std::numeric_limits NL; + float f = static_cast(x); + + if (NL::is_signed) + { + // const float => VC2008 computes it at compile time + // static const float => VC2008 computes it the first time we get here, stores it to memory with static guard and all that. + const float divisor = 1.0f/(2*static_cast(NL::max())+1); + return (2*f+1)*divisor; + } + else + { + return f/NL::max(); + } + } +}; + +template +struct FixedToFloat +{ + static const bool identity = false; + + typedef float OutputType; + + static float convert(FromType x) + { + const float divisor = 1.0f / static_cast(static_cast(1) << ScaleBits); + return static_cast(x) * divisor; + } +}; + +// Widen types: +// static const unsigned int initialWidth: number of components before conversion +// static const unsigned int finalWidth: number of components after conversion + +// Float is supported at any size. +template +struct NoWiden +{ + static const std::size_t initialWidth = N; + static const std::size_t finalWidth = N; +}; + +// SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components +template +struct WidenToEven +{ + static const std::size_t initialWidth = N; + static const std::size_t finalWidth = N+(N&1); +}; + +template +struct WidenToFour +{ + static const std::size_t initialWidth = N; + static const std::size_t finalWidth = 4; +}; + +// Most types have 0 and 1 that are just that. +template +struct SimpleDefaultValues +{ + static T zero() { return static_cast(0); } + static T one() { return static_cast(1); } +}; + +// But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value. +template +struct NormalizedDefaultValues +{ + static T zero() { return static_cast(0); } + static T one() { return std::numeric_limits::max(); } +}; + +// Converter: +// static const bool identity: true if this is an identity transform (with no widening) +// static const std::size_t finalSize: number of bytes per output vertex +// static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert an array of vertices. Input may be strided, but output will be unstrided. + +template > +struct VertexDataConverter +{ + typedef typename Converter::OutputType OutputType; + typedef InT InputType; + + static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity; + static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType); + + static void convertArray(const InputType *in, std::size_t stride, std::size_t n, OutputType *out) + { + for (std::size_t i = 0; i < n; i++) + { + const InputType *ein = pointerAddBytes(in, i * stride); + + copyComponent(out, ein, 0, static_cast(DefaultValueRule::zero())); + copyComponent(out, ein, 1, static_cast(DefaultValueRule::zero())); + copyComponent(out, ein, 2, static_cast(DefaultValueRule::zero())); + copyComponent(out, ein, 3, static_cast(DefaultValueRule::one())); + + out += WidenRule::finalWidth; + } + } + + static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out) + { + return convertArray(static_cast(in), stride, n, static_cast(out)); + } + + private: + // Advance the given pointer by a number of bytes (not pointed-to elements). + template + static T *pointerAddBytes(T *basePtr, std::size_t numBytes) + { + return reinterpret_cast(reinterpret_cast(basePtr) + numBytes); + } + + static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue) + { + if (WidenRule::finalWidth > elementindex) + { + if (WidenRule::initialWidth > elementindex) + { + out[elementindex] = Converter::convert(in[elementindex]); + } + else + { + out[elementindex] = defaultvalue; + } + } + } +}; + +} + +#endif // LIBGLESV2_VERTEXCONVERSION_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp deleted file mode 100644 index 0624a61160..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp +++ /dev/null @@ -1,688 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// renderer11_utils.cpp: Conversion functions and other utility routines -// specific to the D3D11 renderer. - -#include "libGLESv2/renderer/renderer11_utils.h" - -#include "common/debug.h" - -namespace gl_d3d11 -{ - -D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha) -{ - D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO; - - switch (glBlend) - { - case GL_ZERO: d3dBlend = D3D11_BLEND_ZERO; break; - case GL_ONE: d3dBlend = D3D11_BLEND_ONE; break; - case GL_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR); break; - case GL_ONE_MINUS_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR); break; - case GL_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR); break; - case GL_ONE_MINUS_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR); break; - case GL_SRC_ALPHA: d3dBlend = D3D11_BLEND_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3D11_BLEND_INV_SRC_ALPHA; break; - case GL_DST_ALPHA: d3dBlend = D3D11_BLEND_DEST_ALPHA; break; - case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3D11_BLEND_INV_DEST_ALPHA; break; - case GL_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break; - case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break; - case GL_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break; - case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break; - case GL_SRC_ALPHA_SATURATE: d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT; break; - default: UNREACHABLE(); - } - - return d3dBlend; -} - -D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp) -{ - D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD; - - switch (glBlendOp) - { - case GL_FUNC_ADD: d3dBlendOp = D3D11_BLEND_OP_ADD; break; - case GL_FUNC_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_SUBTRACT; break; - case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT; break; - default: UNREACHABLE(); - } - - return d3dBlendOp; -} - -UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha) -{ - UINT8 mask = 0; - if (red) - { - mask |= D3D11_COLOR_WRITE_ENABLE_RED; - } - if (green) - { - mask |= D3D11_COLOR_WRITE_ENABLE_GREEN; - } - if (blue) - { - mask |= D3D11_COLOR_WRITE_ENABLE_BLUE; - } - if (alpha) - { - mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA; - } - return mask; -} - -D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode) -{ - D3D11_CULL_MODE cull = D3D11_CULL_NONE; - - if (cullEnabled) - { - switch (cullMode) - { - case GL_FRONT: cull = D3D11_CULL_FRONT; break; - case GL_BACK: cull = D3D11_CULL_BACK; break; - case GL_FRONT_AND_BACK: cull = D3D11_CULL_NONE; break; - default: UNREACHABLE(); - } - } - else - { - cull = D3D11_CULL_NONE; - } - - return cull; -} - -D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison) -{ - D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER; - switch (comparison) - { - case GL_NEVER: d3dComp = D3D11_COMPARISON_NEVER; break; - case GL_ALWAYS: d3dComp = D3D11_COMPARISON_ALWAYS; break; - case GL_LESS: d3dComp = D3D11_COMPARISON_LESS; break; - case GL_LEQUAL: d3dComp = D3D11_COMPARISON_LESS_EQUAL; break; - case GL_EQUAL: d3dComp = D3D11_COMPARISON_EQUAL; break; - case GL_GREATER: d3dComp = D3D11_COMPARISON_GREATER; break; - case GL_GEQUAL: d3dComp = D3D11_COMPARISON_GREATER_EQUAL; break; - case GL_NOTEQUAL: d3dComp = D3D11_COMPARISON_NOT_EQUAL; break; - default: UNREACHABLE(); - } - - return d3dComp; -} - -D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled) -{ - return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; -} - -UINT8 ConvertStencilMask(GLuint stencilmask) -{ - return static_cast(stencilmask); -} - -D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp) -{ - D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP; - - switch (stencilOp) - { - case GL_ZERO: d3dStencilOp = D3D11_STENCIL_OP_ZERO; break; - case GL_KEEP: d3dStencilOp = D3D11_STENCIL_OP_KEEP; break; - case GL_REPLACE: d3dStencilOp = D3D11_STENCIL_OP_REPLACE; break; - case GL_INCR: d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT; break; - case GL_DECR: d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT; break; - case GL_INVERT: d3dStencilOp = D3D11_STENCIL_OP_INVERT; break; - case GL_INCR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_INCR; break; - case GL_DECR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_DECR; break; - default: UNREACHABLE(); - } - - return d3dStencilOp; -} - -D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy) -{ - if (maxAnisotropy > 1.0f) - { - return D3D11_ENCODE_ANISOTROPIC_FILTER(false); - } - else - { - D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT; - D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT; - switch (minFilter) - { - case GL_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break; - case GL_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break; - case GL_NEAREST_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break; - case GL_LINEAR_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break; - case GL_NEAREST_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_LINEAR; break; - case GL_LINEAR_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_LINEAR; break; - default: UNREACHABLE(); - } - - D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT; - switch (magFilter) - { - case GL_NEAREST: dxMag = D3D11_FILTER_TYPE_POINT; break; - case GL_LINEAR: dxMag = D3D11_FILTER_TYPE_LINEAR; break; - default: UNREACHABLE(); - } - - return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip, false); - } -} - -D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap) -{ - switch (wrap) - { - case GL_REPEAT: return D3D11_TEXTURE_ADDRESS_WRAP; - case GL_CLAMP_TO_EDGE: return D3D11_TEXTURE_ADDRESS_CLAMP; - case GL_MIRRORED_REPEAT: return D3D11_TEXTURE_ADDRESS_MIRROR; - default: UNREACHABLE(); - } - - return D3D11_TEXTURE_ADDRESS_WRAP; -} - -FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset) -{ - return (minFilter == GL_NEAREST || minFilter == GL_LINEAR) ? static_cast(lodOffset) : -FLT_MAX; -} - -FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset) -{ - return (minFilter == GL_NEAREST || minFilter == GL_LINEAR) ? static_cast(lodOffset) : FLT_MAX; -} - -} - -namespace d3d11_gl -{ - -GLenum ConvertBackBufferFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: return GL_RGBA8_OES; - case DXGI_FORMAT_B8G8R8A8_UNORM: return GL_BGRA8_EXT; - default: - UNREACHABLE(); - } - - return GL_RGBA8_OES; -} - -GLenum ConvertDepthStencilFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_UNKNOWN: return GL_NONE; - case DXGI_FORMAT_D16_UNORM: return GL_DEPTH_COMPONENT16; - case DXGI_FORMAT_D24_UNORM_S8_UINT: return GL_DEPTH24_STENCIL8_OES; - default: - UNREACHABLE(); - } - - return GL_DEPTH24_STENCIL8_OES; -} - -GLenum ConvertRenderbufferFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_B8G8R8A8_UNORM: - return GL_BGRA8_EXT; - case DXGI_FORMAT_R8G8B8A8_UNORM: - return GL_RGBA8_OES; - case DXGI_FORMAT_D16_UNORM: - return GL_DEPTH_COMPONENT16; - case DXGI_FORMAT_D24_UNORM_S8_UINT: - return GL_DEPTH24_STENCIL8_OES; - default: - UNREACHABLE(); - } - - return GL_RGBA8_OES; -} - -GLenum ConvertTextureInternalFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - return GL_RGBA8_OES; - case DXGI_FORMAT_A8_UNORM: - return GL_ALPHA8_EXT; - case DXGI_FORMAT_BC1_UNORM: - return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - case DXGI_FORMAT_BC2_UNORM: - return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE; - case DXGI_FORMAT_BC3_UNORM: - return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE; - case DXGI_FORMAT_R32G32B32A32_FLOAT: - return GL_RGBA32F_EXT; - case DXGI_FORMAT_R32G32B32_FLOAT: - return GL_RGB32F_EXT; - case DXGI_FORMAT_R16G16B16A16_FLOAT: - return GL_RGBA16F_EXT; - case DXGI_FORMAT_B8G8R8A8_UNORM: - return GL_BGRA8_EXT; - case DXGI_FORMAT_R8_UNORM: - return GL_R8_EXT; - case DXGI_FORMAT_R8G8_UNORM: - return GL_RG8_EXT; - case DXGI_FORMAT_R16_FLOAT: - return GL_R16F_EXT; - case DXGI_FORMAT_R16G16_FLOAT: - return GL_RG16F_EXT; - case DXGI_FORMAT_D16_UNORM: - return GL_DEPTH_COMPONENT16; - case DXGI_FORMAT_D24_UNORM_S8_UINT: - return GL_DEPTH24_STENCIL8_OES; - case DXGI_FORMAT_UNKNOWN: - return GL_NONE; - default: - UNREACHABLE(); - } - - return GL_RGBA8_OES; -} - -} - -namespace gl_d3d11 -{ - -DXGI_FORMAT ConvertRenderbufferFormat(GLenum format) -{ - switch (format) - { - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGBA8_OES: - case GL_RGB565: - case GL_RGB8_OES: - return DXGI_FORMAT_R8G8B8A8_UNORM; - case GL_BGRA8_EXT: - return DXGI_FORMAT_B8G8R8A8_UNORM; - case GL_DEPTH_COMPONENT16: - return DXGI_FORMAT_D16_UNORM; - case GL_STENCIL_INDEX8: - case GL_DEPTH24_STENCIL8_OES: - return DXGI_FORMAT_D24_UNORM_S8_UINT; - default: - UNREACHABLE(); - } - - return DXGI_FORMAT_R8G8B8A8_UNORM; -} - -DXGI_FORMAT ConvertTextureFormat(GLenum internalformat, D3D_FEATURE_LEVEL featureLevel) -{ - switch (internalformat) - { - case GL_RGB565: - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGB8_OES: - case GL_RGBA8_OES: - case GL_LUMINANCE8_EXT: - case GL_LUMINANCE8_ALPHA8_EXT: - return DXGI_FORMAT_R8G8B8A8_UNORM; - case GL_ALPHA8_EXT: - return featureLevel >= D3D_FEATURE_LEVEL_10_0 ? DXGI_FORMAT_A8_UNORM : DXGI_FORMAT_B8G8R8A8_UNORM; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - return DXGI_FORMAT_BC1_UNORM; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - return DXGI_FORMAT_BC2_UNORM; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - return DXGI_FORMAT_BC3_UNORM; - case GL_RGBA32F_EXT: - case GL_ALPHA32F_EXT: - case GL_LUMINANCE_ALPHA32F_EXT: - return DXGI_FORMAT_R32G32B32A32_FLOAT; - case GL_RGB32F_EXT: - case GL_LUMINANCE32F_EXT: - return DXGI_FORMAT_R32G32B32A32_FLOAT; - case GL_RGBA16F_EXT: - case GL_ALPHA16F_EXT: - case GL_LUMINANCE_ALPHA16F_EXT: - case GL_RGB16F_EXT: - case GL_LUMINANCE16F_EXT: - return DXGI_FORMAT_R16G16B16A16_FLOAT; - case GL_BGRA8_EXT: - return DXGI_FORMAT_B8G8R8A8_UNORM; - case GL_R8_EXT: - return DXGI_FORMAT_R8_UNORM; - case GL_RG8_EXT: - return DXGI_FORMAT_R8G8_UNORM; - case GL_R16F_EXT: - return DXGI_FORMAT_R16_FLOAT; - case GL_RG16F_EXT: - return DXGI_FORMAT_R16G16_FLOAT; - case GL_DEPTH_COMPONENT16: - return DXGI_FORMAT_D16_UNORM; - case GL_DEPTH_COMPONENT32_OES: - case GL_DEPTH24_STENCIL8_OES: - return DXGI_FORMAT_D24_UNORM_S8_UINT; - case GL_NONE: - return DXGI_FORMAT_UNKNOWN; - default: - UNREACHABLE(); - } - - return DXGI_FORMAT_R8G8B8A8_UNORM; -} - -} - -namespace d3d11 -{ - -void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v) -{ - vertex->x = x; - vertex->y = y; - vertex->u = u; - vertex->v = v; -} - -void SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z, - const gl::Color &color) -{ - vertex->x = x; - vertex->y = y; - vertex->z = z; - vertex->r = color.red; - vertex->g = color.green; - vertex->b = color.blue; - vertex->a = color.alpha; -} - -size_t ComputePixelSizeBits(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_R1_UNORM: - return 1; - - case DXGI_FORMAT_A8_UNORM: - case DXGI_FORMAT_R8_SINT: - case DXGI_FORMAT_R8_SNORM: - case DXGI_FORMAT_R8_TYPELESS: - case DXGI_FORMAT_R8_UINT: - case DXGI_FORMAT_R8_UNORM: - return 8; - - case DXGI_FORMAT_B5G5R5A1_UNORM: - case DXGI_FORMAT_B5G6R5_UNORM: - case DXGI_FORMAT_D16_UNORM: - case DXGI_FORMAT_R16_FLOAT: - case DXGI_FORMAT_R16_SINT: - case DXGI_FORMAT_R16_SNORM: - case DXGI_FORMAT_R16_TYPELESS: - case DXGI_FORMAT_R16_UINT: - case DXGI_FORMAT_R16_UNORM: - case DXGI_FORMAT_R8G8_SINT: - case DXGI_FORMAT_R8G8_SNORM: - case DXGI_FORMAT_R8G8_TYPELESS: - case DXGI_FORMAT_R8G8_UINT: - case DXGI_FORMAT_R8G8_UNORM: - return 16; - - case DXGI_FORMAT_B8G8R8X8_TYPELESS: - case DXGI_FORMAT_B8G8R8X8_UNORM: - case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: - case DXGI_FORMAT_D24_UNORM_S8_UINT: - case DXGI_FORMAT_D32_FLOAT: - case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: - case DXGI_FORMAT_G8R8_G8B8_UNORM: - case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: - case DXGI_FORMAT_R10G10B10A2_TYPELESS: - case DXGI_FORMAT_R10G10B10A2_UINT: - case DXGI_FORMAT_R10G10B10A2_UNORM: - case DXGI_FORMAT_R11G11B10_FLOAT: - case DXGI_FORMAT_R16G16_FLOAT: - case DXGI_FORMAT_R16G16_SINT: - case DXGI_FORMAT_R16G16_SNORM: - case DXGI_FORMAT_R16G16_TYPELESS: - case DXGI_FORMAT_R16G16_UINT: - case DXGI_FORMAT_R16G16_UNORM: - case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: - case DXGI_FORMAT_R24G8_TYPELESS: - case DXGI_FORMAT_R32_FLOAT: - case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: - case DXGI_FORMAT_R32_SINT: - case DXGI_FORMAT_R32_TYPELESS: - case DXGI_FORMAT_R32_UINT: - case DXGI_FORMAT_R8G8_B8G8_UNORM: - case DXGI_FORMAT_R8G8B8A8_SINT: - case DXGI_FORMAT_R8G8B8A8_SNORM: - case DXGI_FORMAT_R8G8B8A8_TYPELESS: - case DXGI_FORMAT_R8G8B8A8_UINT: - case DXGI_FORMAT_R8G8B8A8_UNORM: - case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: - case DXGI_FORMAT_B8G8R8A8_TYPELESS: - case DXGI_FORMAT_B8G8R8A8_UNORM: - case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: - case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: - case DXGI_FORMAT_X24_TYPELESS_G8_UINT: - case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: - return 32; - - case DXGI_FORMAT_R16G16B16A16_FLOAT: - case DXGI_FORMAT_R16G16B16A16_SINT: - case DXGI_FORMAT_R16G16B16A16_SNORM: - case DXGI_FORMAT_R16G16B16A16_TYPELESS: - case DXGI_FORMAT_R16G16B16A16_UINT: - case DXGI_FORMAT_R16G16B16A16_UNORM: - case DXGI_FORMAT_R32G32_FLOAT: - case DXGI_FORMAT_R32G32_SINT: - case DXGI_FORMAT_R32G32_TYPELESS: - case DXGI_FORMAT_R32G32_UINT: - case DXGI_FORMAT_R32G8X24_TYPELESS: - return 64; - - case DXGI_FORMAT_R32G32B32_FLOAT: - case DXGI_FORMAT_R32G32B32_SINT: - case DXGI_FORMAT_R32G32B32_TYPELESS: - case DXGI_FORMAT_R32G32B32_UINT: - return 96; - - case DXGI_FORMAT_R32G32B32A32_FLOAT: - case DXGI_FORMAT_R32G32B32A32_SINT: - case DXGI_FORMAT_R32G32B32A32_TYPELESS: - case DXGI_FORMAT_R32G32B32A32_UINT: - return 128; - - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_SNORM: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - return 4; - - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - return 8; - - default: - return 0; - } -} - -size_t ComputeBlockSizeBits(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_SNORM: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - return ComputePixelSizeBits(format) * 16; - default: - UNREACHABLE(); - return 0; - } -} - -bool IsCompressed(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_SNORM: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - return true; - case DXGI_FORMAT_UNKNOWN: - UNREACHABLE(); - return false; - default: - return false; - } -} - -unsigned int GetTextureFormatDimensionAlignment(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_SNORM: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - return 4; - case DXGI_FORMAT_UNKNOWN: - UNREACHABLE(); - return 1; - default: - return 1; - } -} - -bool IsDepthStencilFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: - case DXGI_FORMAT_D32_FLOAT: - case DXGI_FORMAT_D24_UNORM_S8_UINT: - case DXGI_FORMAT_D16_UNORM: - return true; - default: - return false; - } -} - -DXGI_FORMAT GetDepthTextureFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_R32G8X24_TYPELESS; - case DXGI_FORMAT_D32_FLOAT: return DXGI_FORMAT_R32_TYPELESS; - case DXGI_FORMAT_D24_UNORM_S8_UINT: return DXGI_FORMAT_R24G8_TYPELESS; - case DXGI_FORMAT_D16_UNORM: return DXGI_FORMAT_R16_TYPELESS; - default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; - } -} - -DXGI_FORMAT GetDepthShaderResourceFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; - case DXGI_FORMAT_D32_FLOAT: return DXGI_FORMAT_R32_UINT; - case DXGI_FORMAT_D24_UNORM_S8_UINT: return DXGI_FORMAT_R24_UNORM_X8_TYPELESS; - case DXGI_FORMAT_D16_UNORM: return DXGI_FORMAT_R16_UNORM; - default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; - } -} - -HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) -{ -#if defined(_DEBUG) - return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name); -#else - return S_OK; -#endif -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.h deleted file mode 100644 index 70ad4fea2b..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.h +++ /dev/null @@ -1,95 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// renderer11_utils.h: Conversion functions and other utility routines -// specific to the D3D11 renderer. - -#ifndef LIBGLESV2_RENDERER_RENDERER11_UTILS_H -#define LIBGLESV2_RENDERER_RENDERER11_UTILS_H - -#include "libGLESv2/angletypes.h" - -namespace gl_d3d11 -{ - -D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha); -D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp); -UINT8 ConvertColorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha); - -D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode); - -D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison); -D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled); -UINT8 ConvertStencilMask(GLuint stencilmask); -D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp); - -D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy); -D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap); -FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset); -FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset); - -DXGI_FORMAT ConvertRenderbufferFormat(GLenum format); -DXGI_FORMAT ConvertTextureFormat(GLenum format, D3D_FEATURE_LEVEL featureLevel); -} - -namespace d3d11_gl -{ - -GLenum ConvertBackBufferFormat(DXGI_FORMAT format); -GLenum ConvertDepthStencilFormat(DXGI_FORMAT format); -GLenum ConvertRenderbufferFormat(DXGI_FORMAT format); -GLenum ConvertTextureInternalFormat(DXGI_FORMAT format); - -} - -namespace d3d11 -{ - -struct PositionTexCoordVertex -{ - float x, y; - float u, v; -}; -void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v); - -struct PositionDepthColorVertex -{ - float x, y, z; - float r, g, b, a; -}; -void SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z, - const gl::Color &color); - -size_t ComputePixelSizeBits(DXGI_FORMAT format); -size_t ComputeBlockSizeBits(DXGI_FORMAT format); - -bool IsCompressed(DXGI_FORMAT format); -unsigned int GetTextureFormatDimensionAlignment(DXGI_FORMAT format); - -bool IsDepthStencilFormat(DXGI_FORMAT format); -DXGI_FORMAT GetDepthTextureFormat(DXGI_FORMAT format); -DXGI_FORMAT GetDepthShaderResourceFormat(DXGI_FORMAT format); - -HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name); - -inline bool isDeviceLostError(HRESULT errorCode) -{ - switch (errorCode) - { - case DXGI_ERROR_DEVICE_HUNG: - case DXGI_ERROR_DEVICE_REMOVED: - case DXGI_ERROR_DEVICE_RESET: - case DXGI_ERROR_DRIVER_INTERNAL_ERROR: - case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE: - return true; - default: - return false; - } -} - -} - -#endif // LIBGLESV2_RENDERER_RENDERER11_UTILS_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/renderer9_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/renderer9_utils.cpp deleted file mode 100644 index da75d465e3..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/renderer9_utils.cpp +++ /dev/null @@ -1,500 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// renderer9_utils.cpp: Conversion functions and other utility routines -// specific to the D3D9 renderer. - -#include "libGLESv2/renderer/renderer9_utils.h" -#include "libGLESv2/mathutil.h" -#include "libGLESv2/Context.h" - -#include "common/debug.h" - -namespace gl_d3d9 -{ - -D3DCMPFUNC ConvertComparison(GLenum comparison) -{ - D3DCMPFUNC d3dComp = D3DCMP_ALWAYS; - switch (comparison) - { - case GL_NEVER: d3dComp = D3DCMP_NEVER; break; - case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break; - case GL_LESS: d3dComp = D3DCMP_LESS; break; - case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break; - case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break; - case GL_GREATER: d3dComp = D3DCMP_GREATER; break; - case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break; - case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break; - default: UNREACHABLE(); - } - - return d3dComp; -} - -D3DCOLOR ConvertColor(gl::Color color) -{ - return D3DCOLOR_RGBA(gl::unorm<8>(color.red), - gl::unorm<8>(color.green), - gl::unorm<8>(color.blue), - gl::unorm<8>(color.alpha)); -} - -D3DBLEND ConvertBlendFunc(GLenum blend) -{ - D3DBLEND d3dBlend = D3DBLEND_ZERO; - - switch (blend) - { - case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break; - case GL_ONE: d3dBlend = D3DBLEND_ONE; break; - case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break; - case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break; - case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break; - case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break; - case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break; - case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break; - case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break; - case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break; - case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; - case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break; - case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; - case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break; - default: UNREACHABLE(); - } - - return d3dBlend; -} - -D3DBLENDOP ConvertBlendOp(GLenum blendOp) -{ - D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD; - - switch (blendOp) - { - case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break; - case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break; - case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break; - default: UNREACHABLE(); - } - - return d3dBlendOp; -} - -D3DSTENCILOP ConvertStencilOp(GLenum stencilOp) -{ - D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP; - - switch (stencilOp) - { - case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break; - case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break; - case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break; - case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break; - case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break; - case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break; - case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break; - case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break; - default: UNREACHABLE(); - } - - return d3dStencilOp; -} - -D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap) -{ - D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP; - - switch (wrap) - { - case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break; - case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break; - case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break; - default: UNREACHABLE(); - } - - return d3dWrap; -} - -D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace) -{ - D3DCULL cull = D3DCULL_CCW; - switch (cullFace) - { - case GL_FRONT: - cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW); - break; - case GL_BACK: - cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW); - break; - case GL_FRONT_AND_BACK: - cull = D3DCULL_NONE; // culling will be handled during draw - break; - default: UNREACHABLE(); - } - - return cull; -} - -D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace) -{ - D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X; - - switch (cubeFace) - { - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - face = D3DCUBEMAP_FACE_POSITIVE_X; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - face = D3DCUBEMAP_FACE_NEGATIVE_X; - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - face = D3DCUBEMAP_FACE_POSITIVE_Y; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - face = D3DCUBEMAP_FACE_NEGATIVE_Y; - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - face = D3DCUBEMAP_FACE_POSITIVE_Z; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - face = D3DCUBEMAP_FACE_NEGATIVE_Z; - break; - default: UNREACHABLE(); - } - - return face; -} - -DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha) -{ - return (red ? D3DCOLORWRITEENABLE_RED : 0) | - (green ? D3DCOLORWRITEENABLE_GREEN : 0) | - (blue ? D3DCOLORWRITEENABLE_BLUE : 0) | - (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0); -} - -D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy) -{ - if (maxAnisotropy > 1.0f) - { - return D3DTEXF_ANISOTROPIC; - } - - D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT; - switch (magFilter) - { - case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break; - case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break; - default: UNREACHABLE(); - } - - return d3dMagFilter; -} - -void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy) -{ - switch (minFilter) - { - case GL_NEAREST: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_NONE; - break; - case GL_LINEAR: - *d3dMinFilter = D3DTEXF_LINEAR; - *d3dMipFilter = D3DTEXF_NONE; - break; - case GL_NEAREST_MIPMAP_NEAREST: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_POINT; - break; - case GL_LINEAR_MIPMAP_NEAREST: - *d3dMinFilter = D3DTEXF_LINEAR; - *d3dMipFilter = D3DTEXF_POINT; - break; - case GL_NEAREST_MIPMAP_LINEAR: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_LINEAR; - break; - case GL_LINEAR_MIPMAP_LINEAR: - *d3dMinFilter = D3DTEXF_LINEAR; - *d3dMipFilter = D3DTEXF_LINEAR; - break; - default: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_NONE; - UNREACHABLE(); - } - - if (maxAnisotropy > 1.0f) - { - *d3dMinFilter = D3DTEXF_ANISOTROPIC; - } -} - -D3DFORMAT ConvertRenderbufferFormat(GLenum format) -{ - switch (format) - { - case GL_NONE: return D3DFMT_NULL; - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGBA8_OES: return D3DFMT_A8R8G8B8; - case GL_RGB565: return D3DFMT_R5G6B5; - case GL_RGB8_OES: return D3DFMT_X8R8G8B8; - case GL_DEPTH_COMPONENT16: - case GL_STENCIL_INDEX8: - case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8; - default: UNREACHABLE(); return D3DFMT_A8R8G8B8; - } -} - -D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples) -{ - if (samples <= 1) - return D3DMULTISAMPLE_NONE; - else - return (D3DMULTISAMPLE_TYPE)samples; -} - -} - -namespace d3d9_gl -{ - -unsigned int GetStencilSize(D3DFORMAT stencilFormat) -{ - if (stencilFormat == D3DFMT_INTZ) - { - return 8; - } - switch(stencilFormat) - { - case D3DFMT_D24FS8: - case D3DFMT_D24S8: - return 8; - case D3DFMT_D24X4S4: - return 4; - case D3DFMT_D15S1: - return 1; - case D3DFMT_D16_LOCKABLE: - case D3DFMT_D32: - case D3DFMT_D24X8: - case D3DFMT_D32F_LOCKABLE: - case D3DFMT_D16: - return 0; - //case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only - //case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only - default: - return 0; - } -} - -unsigned int GetAlphaSize(D3DFORMAT colorFormat) -{ - switch (colorFormat) - { - case D3DFMT_A16B16G16R16F: - return 16; - case D3DFMT_A32B32G32R32F: - return 32; - case D3DFMT_A2R10G10B10: - return 2; - case D3DFMT_A8R8G8B8: - return 8; - case D3DFMT_A1R5G5B5: - return 1; - case D3DFMT_X8R8G8B8: - case D3DFMT_R5G6B5: - return 0; - default: - return 0; - } -} - -GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type) -{ - if (type == D3DMULTISAMPLE_NONMASKABLE) - return 0; - else - return type; -} - -bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format) -{ - switch (d3dformat) - { - case D3DFMT_L8: - return (format == GL_LUMINANCE); - case D3DFMT_A8L8: - return (format == GL_LUMINANCE_ALPHA); - case D3DFMT_DXT1: - return (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT); - case D3DFMT_DXT3: - return (format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); - case D3DFMT_DXT5: - return (format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); - case D3DFMT_A8R8G8B8: - case D3DFMT_A16B16G16R16F: - case D3DFMT_A32B32G32R32F: - return (format == GL_RGBA || format == GL_BGRA_EXT); - case D3DFMT_X8R8G8B8: - return (format == GL_RGB); - default: - if (d3dformat == D3DFMT_INTZ && gl::IsDepthTexture(format)) - return true; - return false; - } -} - -GLenum ConvertBackBufferFormat(D3DFORMAT format) -{ - switch (format) - { - case D3DFMT_A4R4G4B4: return GL_RGBA4; - case D3DFMT_A8R8G8B8: return GL_RGBA8_OES; - case D3DFMT_A1R5G5B5: return GL_RGB5_A1; - case D3DFMT_R5G6B5: return GL_RGB565; - case D3DFMT_X8R8G8B8: return GL_RGB8_OES; - default: - UNREACHABLE(); - } - - return GL_RGBA4; -} - -GLenum ConvertDepthStencilFormat(D3DFORMAT format) -{ - if (format == D3DFMT_INTZ) - { - return GL_DEPTH24_STENCIL8_OES; - } - switch (format) - { - case D3DFMT_D16: - case D3DFMT_D24X8: - return GL_DEPTH_COMPONENT16; - case D3DFMT_D24S8: - return GL_DEPTH24_STENCIL8_OES; - case D3DFMT_UNKNOWN: - return GL_NONE; - default: - UNREACHABLE(); - } - - return GL_DEPTH24_STENCIL8_OES; -} - -GLenum ConvertRenderTargetFormat(D3DFORMAT format) -{ - if (format == D3DFMT_INTZ) - { - return GL_DEPTH24_STENCIL8_OES; - } - - 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; - case D3DFMT_D16: - case D3DFMT_D24X8: - return GL_DEPTH_COMPONENT16; - case D3DFMT_D24S8: - return GL_DEPTH24_STENCIL8_OES; - case D3DFMT_UNKNOWN: - return GL_NONE; - default: - UNREACHABLE(); - } - - return GL_RGBA4; -} - -GLenum GetEquivalentFormat(D3DFORMAT format) -{ - if (format == D3DFMT_INTZ) - return GL_DEPTH24_STENCIL8_OES; - if (format == D3DFMT_NULL) - return GL_NONE; - - 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; - case D3DFMT_D16: return GL_DEPTH_COMPONENT16; - case D3DFMT_D24S8: return GL_DEPTH24_STENCIL8_OES; - case D3DFMT_UNKNOWN: return GL_NONE; - case D3DFMT_DXT1: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - case D3DFMT_DXT3: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE; - case D3DFMT_DXT5: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE; - case D3DFMT_A32B32G32R32F: return GL_RGBA32F_EXT; - case D3DFMT_A16B16G16R16F: return GL_RGBA16F_EXT; - case D3DFMT_L8: return GL_LUMINANCE8_EXT; - case D3DFMT_A8L8: return GL_LUMINANCE8_ALPHA8_EXT; - default: UNREACHABLE(); - return GL_NONE; - } -} - -} - -namespace d3d9 -{ - -bool IsCompressedFormat(D3DFORMAT surfaceFormat) -{ - switch(surfaceFormat) - { - case D3DFMT_DXT1: - case D3DFMT_DXT2: - case D3DFMT_DXT3: - case D3DFMT_DXT4: - case D3DFMT_DXT5: - return true; - default: - return false; - } -} - -size_t ComputeRowSize(D3DFORMAT format, unsigned int width) -{ - if (format == D3DFMT_INTZ) - { - return 4 * width; - } - switch (format) - { - case D3DFMT_L8: - return 1 * width; - case D3DFMT_A8L8: - return 2 * width; - case D3DFMT_X8R8G8B8: - case D3DFMT_A8R8G8B8: - return 4 * width; - case D3DFMT_A16B16G16R16F: - return 8 * width; - case D3DFMT_A32B32G32R32F: - return 16 * width; - case D3DFMT_DXT1: - return 8 * ((width + 3) / 4); - case D3DFMT_DXT3: - case D3DFMT_DXT5: - return 16 * ((width + 3) / 4); - default: - UNREACHABLE(); - return 0; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/renderer9_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/renderer9_utils.h deleted file mode 100644 index bf6cdf1ea6..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/renderer9_utils.h +++ /dev/null @@ -1,74 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// renderer9_utils.h: Conversion functions and other utility routines -// specific to the D3D9 renderer - -#ifndef LIBGLESV2_RENDERER_RENDERER9_UTILS_H -#define LIBGLESV2_RENDERER_RENDERER9_UTILS_H - -#include "libGLESv2/utilities.h" - -const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z'))); -const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L'))); - -namespace gl_d3d9 -{ - -D3DCMPFUNC ConvertComparison(GLenum comparison); -D3DCOLOR ConvertColor(gl::Color color); -D3DBLEND ConvertBlendFunc(GLenum blend); -D3DBLENDOP ConvertBlendOp(GLenum blendOp); -D3DSTENCILOP ConvertStencilOp(GLenum stencilOp); -D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap); -D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace); -D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace); -DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha); -D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy); -void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy); -D3DFORMAT ConvertRenderbufferFormat(GLenum format); -D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples); - -} - -namespace d3d9_gl -{ - -GLuint GetAlphaSize(D3DFORMAT colorFormat); -GLuint GetStencilSize(D3DFORMAT stencilFormat); - -GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type); - -bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format); -GLenum ConvertBackBufferFormat(D3DFORMAT format); -GLenum ConvertDepthStencilFormat(D3DFORMAT format); -GLenum ConvertRenderTargetFormat(D3DFORMAT format); -GLenum GetEquivalentFormat(D3DFORMAT format); - -} - -namespace d3d9 -{ -bool IsCompressedFormat(D3DFORMAT format); -size_t ComputeRowSize(D3DFORMAT format, unsigned int width); - -inline bool isDeviceLostError(HRESULT errorCode) -{ - switch (errorCode) - { - case D3DERR_DRIVERINTERNALERROR: - case D3DERR_DEVICELOST: - case D3DERR_DEVICEHUNG: - case D3DERR_DEVICEREMOVED: - return true; - default: - return false; - } -} - -} - -#endif // LIBGLESV2_RENDERER_RENDERER9_UTILS_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Blit.ps b/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Blit.ps deleted file mode 100644 index dcb3bd0e76..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Blit.ps +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -sampler2D tex : s0; - -uniform float4 mode : c0; - -// Passthrough Pixel Shader -// Outputs texture 0 sampled at texcoord 0. -float4 passthroughps(float4 texcoord : TEXCOORD0) : COLOR -{ - return tex2D(tex, texcoord.xy); -}; - -// Luminance Conversion Pixel Shader -// Outputs sample(tex0, tc0).rrra. -// For LA output (pass A) set C0.X = 1, C0.Y = 0. -// For L output (A = 1) set C0.X = 0, C0.Y = 1. -float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR -{ - float4 tmp = tex2D(tex, texcoord.xy); - tmp.w = tmp.w * mode.x + mode.y; - return tmp.xxxw; -}; - -// RGB/A Component Mask Pixel Shader -// Outputs sample(tex0, tc0) with options to force RGB = 0 and/or A = 1. -// To force RGB = 0, set C0.X = 0, otherwise C0.X = 1. -// To force A = 1, set C0.Z = 0, C0.W = 1, otherwise C0.Z = 1, C0.W = 0. -float4 componentmaskps(float4 texcoord : TEXCOORD0) : COLOR -{ - float4 tmp = tex2D(tex, texcoord.xy); - tmp.xyz = tmp.xyz * mode.x; - tmp.w = tmp.w * mode.z + mode.w; - return tmp; -}; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Blit.vs b/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Blit.vs deleted file mode 100644 index 3a36980b93..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Blit.vs +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -struct VS_OUTPUT -{ - float4 position : POSITION; - float4 texcoord : TEXCOORD0; -}; - -uniform float4 halfPixelSize : c0; - -// Standard Vertex Shader -// Input 0 is the homogenous position. -// Outputs the homogenous position as-is. -// Outputs a tex coord with (0,0) in the upper-left corner of the screen and (1,1) in the bottom right. -// C0.X must be negative half-pixel width, C0.Y must be half-pixel height. C0.ZW must be 0. -VS_OUTPUT standardvs(in float4 position : POSITION) -{ - VS_OUTPUT Out; - - Out.position = position + halfPixelSize; - Out.texcoord = position * float4(0.5, -0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0); - - return Out; -}; - -// Flip Y Vertex Shader -// Input 0 is the homogenous position. -// Outputs the homogenous position as-is. -// Outputs a tex coord with (0,1) in the upper-left corner of the screen and (1,0) in the bottom right. -// C0.XY must be the half-pixel width and height. C0.ZW must be 0. -VS_OUTPUT flipyvs(in float4 position : POSITION) -{ - VS_OUTPUT Out; - - Out.position = position + halfPixelSize; - Out.texcoord = position * float4(0.5, 0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0); - - return Out; -}; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl deleted file mode 100644 index cb132dc99c..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl +++ /dev/null @@ -1,42 +0,0 @@ -void VS_Clear( in float3 inPosition : POSITION, in float4 inColor : COLOR, - out float4 outPosition : SV_POSITION, out float4 outColor : COLOR) -{ - outPosition = float4(inPosition, 1.0f); - outColor = inColor; -} - -// Assume we are in SM4+, which has 8 color outputs -struct PS_OutputMultiple -{ - float4 color0 : SV_TARGET0; - float4 color1 : SV_TARGET1; - float4 color2 : SV_TARGET2; - float4 color3 : SV_TARGET3; -#ifdef SM4 - float4 color4 : SV_TARGET4; - float4 color5 : SV_TARGET5; - float4 color6 : SV_TARGET6; - float4 color7 : SV_TARGET7; -#endif -}; - -PS_OutputMultiple PS_ClearMultiple(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) -{ - PS_OutputMultiple outColor; - outColor.color0 = inColor; - outColor.color1 = inColor; - outColor.color2 = inColor; - outColor.color3 = inColor; -#ifdef SM4 - outColor.color4 = inColor; - outColor.color5 = inColor; - outColor.color6 = inColor; - outColor.color7 = inColor; -#endif - return outColor; -} - -float4 PS_ClearSingle(in float4 inPosition : SV_Position, in float4 inColor : COLOR) : SV_Target0 -{ - return inColor; -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Passthrough11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Passthrough11.hlsl deleted file mode 100644 index 43b7801efc..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Passthrough11.hlsl +++ /dev/null @@ -1,29 +0,0 @@ -Texture2D Texture : register(t0); -SamplerState Sampler : register(s0); - -void VS_Passthrough( in float2 inPosition : POSITION, in float2 inTexCoord : TEXCOORD0, - out float4 outPosition : SV_POSITION, out float2 outTexCoord : TEXCOORD0) -{ - outPosition = float4(inPosition, 0.0f, 1.0f); - outTexCoord = inTexCoord; -} - -float4 PS_PassthroughRGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return Texture.Sample(Sampler, inTexCoord).rgba; -} - -float4 PS_PassthroughRGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return float4(Texture.Sample(Sampler, inTexCoord).rgb, 1.0f); -} - -float4 PS_PassthroughLum(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return float4(Texture.Sample(Sampler, inTexCoord).rrr, 1.0f); -} - -float4 PS_PassthroughLumAlpha(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return Texture.Sample(Sampler, inTexCoord).rrra; -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h b/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h deleted file mode 100644 index 590b9d48a3..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h +++ /dev/null @@ -1,203 +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. -// - -// vertexconversion.h: A library of vertex conversion classes that can be used to build -// the FormatConverter objects used by the buffer conversion system. - -#ifndef LIBGLESV2_VERTEXCONVERSION_H_ -#define LIBGLESV2_VERTEXCONVERSION_H_ - -namespace rx -{ - -// Conversion types: -// static const bool identity: true if this is an identity transform, false otherwise -// static U convert(T): convert a single element from the input type to the output type -// typedef ... OutputType: the type produced by this conversion - -template -struct Identity -{ - static const bool identity = true; - - typedef T OutputType; - - static T convert(T x) - { - return x; - } -}; - -template -struct Cast -{ - static const bool identity = false; - - typedef ToT OutputType; - - static ToT convert(FromT x) - { - return static_cast(x); - } -}; - -template -struct Cast -{ - static const bool identity = true; - - typedef T OutputType; - - static T convert(T x) - { - return static_cast(x); - } -}; - -template -struct Normalize -{ - static const bool identity = false; - - typedef float OutputType; - - static float convert(T x) - { - typedef std::numeric_limits NL; - float f = static_cast(x); - - if (NL::is_signed) - { - // const float => VC2008 computes it at compile time - // static const float => VC2008 computes it the first time we get here, stores it to memory with static guard and all that. - const float divisor = 1.0f/(2*static_cast(NL::max())+1); - return (2*f+1)*divisor; - } - else - { - return f/NL::max(); - } - } -}; - -template -struct FixedToFloat -{ - static const bool identity = false; - - typedef float OutputType; - - static float convert(FromType x) - { - const float divisor = 1.0f / static_cast(static_cast(1) << ScaleBits); - return static_cast(x) * divisor; - } -}; - -// Widen types: -// static const unsigned int initialWidth: number of components before conversion -// static const unsigned int finalWidth: number of components after conversion - -// Float is supported at any size. -template -struct NoWiden -{ - static const std::size_t initialWidth = N; - static const std::size_t finalWidth = N; -}; - -// SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components -template -struct WidenToEven -{ - static const std::size_t initialWidth = N; - static const std::size_t finalWidth = N+(N&1); -}; - -template -struct WidenToFour -{ - static const std::size_t initialWidth = N; - static const std::size_t finalWidth = 4; -}; - -// Most types have 0 and 1 that are just that. -template -struct SimpleDefaultValues -{ - static T zero() { return static_cast(0); } - static T one() { return static_cast(1); } -}; - -// But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value. -template -struct NormalizedDefaultValues -{ - static T zero() { return static_cast(0); } - static T one() { return std::numeric_limits::max(); } -}; - -// Converter: -// static const bool identity: true if this is an identity transform (with no widening) -// static const std::size_t finalSize: number of bytes per output vertex -// static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert an array of vertices. Input may be strided, but output will be unstrided. - -template > -struct VertexDataConverter -{ - typedef typename Converter::OutputType OutputType; - typedef InT InputType; - - static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity; - static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType); - - static void convertArray(const InputType *in, std::size_t stride, std::size_t n, OutputType *out) - { - for (std::size_t i = 0; i < n; i++) - { - const InputType *ein = pointerAddBytes(in, i * stride); - - copyComponent(out, ein, 0, static_cast(DefaultValueRule::zero())); - copyComponent(out, ein, 1, static_cast(DefaultValueRule::zero())); - copyComponent(out, ein, 2, static_cast(DefaultValueRule::zero())); - copyComponent(out, ein, 3, static_cast(DefaultValueRule::one())); - - out += WidenRule::finalWidth; - } - } - - static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out) - { - return convertArray(static_cast(in), stride, n, static_cast(out)); - } - - private: - // Advance the given pointer by a number of bytes (not pointed-to elements). - template - static T *pointerAddBytes(T *basePtr, std::size_t numBytes) - { - return reinterpret_cast(reinterpret_cast(basePtr) + numBytes); - } - - static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue) - { - if (WidenRule::finalWidth > elementindex) - { - if (WidenRule::initialWidth > elementindex) - { - out[elementindex] = Converter::convert(in[elementindex]); - } - else - { - out[elementindex] = defaultvalue; - } - } - } -}; - -} - -#endif // LIBGLESV2_VERTEXCONVERSION_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/utilities.cpp b/src/3rdparty/angle/src/libGLESv2/utilities.cpp index 8fd193b164..30765ffba0 100644 --- a/src/3rdparty/angle/src/libGLESv2/utilities.cpp +++ b/src/3rdparty/angle/src/libGLESv2/utilities.cpp @@ -9,13 +9,13 @@ #include "libGLESv2/utilities.h" #include "libGLESv2/mathutil.h" - #if defined(ANGLE_OS_WINRT) -#include -#include -#include -#include -using namespace ABI::Windows::Storage; +# include +# include +# include +# include + using namespace Microsoft::WRL; + using namespace ABI::Windows::Storage; #endif namespace gl @@ -745,29 +745,43 @@ bool IsTriangleMode(GLenum drawMode) std::string getTempPath() { -#if defined(ANGLE_OS_WINRT) +#if !defined(ANGLE_OS_WINRT) + char path[MAX_PATH]; + DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path); + if (pathLen == 0) + { + UNREACHABLE(); + return std::string(); + } + UINT unique = GetTempFileNameA(path, "sh", 0, path); + if (unique == 0) + { + UNREACHABLE(); + return std::string(); + } +#else static std::string path; while (path.empty()) { - IApplicationDataStatics *applicationDataFactory; - HRESULT result = RoGetActivationFactory(Microsoft::WRL::Wrappers::HStringReference(RuntimeClass_Windows_Storage_ApplicationData).Get(), - IID_PPV_ARGS(&applicationDataFactory)); + ComPtr factory; + Wrappers::HStringReference classId(RuntimeClass_Windows_Storage_ApplicationData); + HRESULT result = RoGetActivationFactory(classId.Get(), IID_PPV_ARGS(&factory)); if (FAILED(result)) break; - IApplicationData *applicationData; - result = applicationDataFactory->get_Current(&applicationData); + ComPtr applicationData; + result = factory->get_Current(&applicationData); if (FAILED(result)) break; - IStorageFolder *storageFolder; + ComPtr storageFolder; result = applicationData->get_LocalFolder(&storageFolder); if (FAILED(result)) break; - IStorageItem *localFolder; - result = storageFolder->QueryInterface(IID_PPV_ARGS(&localFolder)); + ComPtr localFolder; + result = storageFolder.As(&localFolder); if (FAILED(result)) break; @@ -784,25 +798,6 @@ std::string getTempPath() break; } } - -#else - - char path[MAX_PATH]; - - DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path); - if (pathLen == 0) - { - UNREACHABLE(); - return std::string(); - } - - UINT unique = GetTempFileNameA(path, "sh", 0, path); - if (unique == 0) - { - UNREACHABLE(); - return std::string(); - } - #endif return path; diff --git a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h index 0d4e1a374c..f725f55b57 100644 --- a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h +++ b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h @@ -28,8 +28,8 @@ #include "GLSLANG/ShaderLang.h" -#include "compiler/InfoSink.h" -#include "compiler/intermediate.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/intermediate.h" class ArrayBoundsClamper { public: diff --git a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h index 72d354dd64..96ac910b08 100644 --- a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h +++ b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h @@ -574,8 +574,6 @@ namespace gl { -extern long **traceSamplingState; - namespace TraceEvent { // Specify these values when the corresponding argument of addTraceEvent is not @@ -793,6 +791,7 @@ private: // TraceEventSamplingStateScope records the current sampling state // and sets a new sampling state. When the scope exists, it restores // the sampling state having recorded. +#if 0 // This is not used by ANGLE and causes a compilation error on MinGW template class SamplingStateScope { public: @@ -820,6 +819,7 @@ public: private: const char* m_previousState; }; +#endif } // namespace TraceEvent -- cgit v1.2.3